наконец то первое нормальное видео которое прям по полкам про чистую архитектуру на го поясняет, ура, я столько пересмотрел видосов, и нескольок раз прочел мартина чистую архитектуру, но это видео прям глаза открыло
Спасибо за доклад, очень круто! Есть пару моментов с которыми я не согласен: 12:00 - плохая идея использовать одну структуру в entity на все слои, объясню почему: мне нужно из controller передать в usecase два поля для пагинации (offset, limit). Почему слой entity (слой enterprise бизнес логики) должен знать про какую-то пагинацию?) 14:20 - плохая практика использовать backticks с json в слое entity, т.к этот слой ничего не должен знать о представлении. То есть, если придет заказчик и скажет, что мне вместо json подавай xml, то придется менять слой entity (получается entity и controller имеют какую-то косвенную связь). К тому же у вас могут быть принципиально разные структуры, что в слое entity, что в controller.
Разумеется. Но это уже детали. Я высокоуровнево и доступно старался объяснить. В реальном мире нужен пакет dto в котором это всё будет находится. Я dto использую для связи controller usecase. Большие и сложные dto бывает доходят и до адаптеров. Ну и внутри entity постепенно появляются другие пакеты по мере разрастания логики. Главное понять как управлять сложностью и где проводить границы между разными частями сервиса.
@@neprja а каким образом стоит декаплить пакеты, в случае если мы в юзкейсе реализовали проверку(errors.As, errors.Is) и хендлинг кастомных ошибок(созданных errors.New) , возвращаемых пакетом, отвечающим, например, за интеграцию с другим микросервисом. Мы будем его импортировать, чтобы иметь доступ к переменным и типам тех ошибок. Или есть альтеративный подход, где мы оперируем абстракцией?
О! Не смотря это видео и только начав изучать чистую архитектуру я переделал одно микросервисное приложение под неё. Не знал как лучше архитектурно реализовывать многие вещи (нужна ли отдельная структура для юзкейсов, в ней ли должен храниться репозиторий, где обращаться к другому микросервису) и написал как смог придумать. Сейчас смотрю это видео и понимаю, что почти все делал правильно! Но теперь уже есть точное понимание, зачем и почему так. Спасибо, очень конкретное, дельное и познавательное видео.
В рамках микросервисов нет деления на понятние application logic и core business logic. Потому что в самом смысле микросервисов заложено, что микросервисы должны быть слабосвязаны между собой, а соответственно и сквозных данных/логики между ними должно быть по минимуму. Это разделение было для стандартных монолитов, и за счет этого разделения возможно было бы использовать один единый удобный слой core business logic для разных целевых модулей/блоков приложения. Например, одна модель счет фактуры для разных сценариев и интерфейсов использования: наборщик на складе, водитель-экспедитор, приемщик и т.д. Они работают каждый через свой слой абстракции(application logic) с одной общей моделью(core business logic). В архитектуре микросервисов это спокойно распиливается на 4(условно) микросервиса.
Спасибо за видео. Очень многое понятно. Но хочется для таких как я 😂(начинающих), объяснить все тоже самое , но на примере конкретного приложения , например файлообменник. И прям на нем показать данный подход
Тоже никогда не понимал, зачем нужно пилить столько dtoшек в рамках микросервиса, особенно при том что всё это делается в папке internal, т.е. переиспользование всего этого добра в других проекта не предполагается... По мне так dto в такой архитектуре должен быть аналогом адаптера типов. Т.е. если вместо одного из модулей или вместо одной из частей системы мы подключаем внешний пакет, который не умеет работать с нашими моделями. В таком случае мы как раз используем dto, чтобы произвести маппинг на нужный формат данных. Но если мы все пилим в локальных, закрытых, не нацеленных на переиспользование в других проектах модулях - нафига этот огород? Прокидывать везде единые модели данных - это нормально. Но при этом если потом понядобится/захочется ввести локальные dto для каких-то сервисов/модулей - это можно легко сделать точечно. Конечно же все вшесказанное работает, если dto и entity совпадают на 90+%. Когда мы там передаем кучу служебных данных, не связанных с моделями - ну тут уж никуда.
Немного не согласен. Во-первых, нет смысла отделять интерфейсом слой контроллеров от слоя UseCase, т.к. UseCase никогда не будет вызывать контроллер, а контроллер вполне имеет право быть в курсе про конкретный UseCase согласно той же диаграмме зависимостей. Ситуации, конечно, разные могут быть, но в принципе это не нужно. И во-вторых, entity могут использоваться по всему проекту по той же причине. DTO никто не отменял, но, это, скорее элемент абстракции, а не ограничения видимости.
@@neprja простите за глупые вопросы, я ещё даже не джун. У вас хорошая слоистость, поэтому пока не просто сразу въехать. Я верно понял, что ваш слой controller это слой port в гексагоналке?
@@neprja спасибо) а могу ещё отнять немного вашего времени вопросом. Часто вижу, что параметры среды не выносятся в отдельный сервис синглтоном, при этом очевидно, что эта функция может иметь несколько итераций построения объекта среды, например default -> flags -> env -> external file (yaml, toml etc). Почему не принято выносить эту процедуру в отдельный entity? Или просто обычно этому нет нужды уделять отдельного внимания?
@@yarbersheer8559 В entity ему точно не место, entity - это сущность бизнес-логики. А параметры среды - это конфигурация для построения объектов архитектуры приложения. Лучшая практика для переменных - делать синглтоном.
Хмм, а как в вашем случае (на 25:50 показано справа) предполагается писать одни и те же методы (`New()`, например) для разных юзкейсов (apple/banana) в одном пакете usecase? Всё-таки надо их делить (создавать подпапки apple/banana внутри usecase) или есть возможность разграничить scope файлов apple/banana, чтобы компилятор не ругался на одинаковые методы? Просто если делить юзкейсы по папкам, тогда инфраструктуру, кажется, нужно выносить в отдельный пакет вне usecase, т.к. её могут использовать несколько юзкейсов (в репозитории из примера инфра лежит внутри usecase)
Спасибо за замечания) На счет репозитория из примера, он немного устарел, туда лучше не смотрите. Идеи со слайдов актуальны. У меня пакет infrastructure находится на одном уровне с controller, entity и usecase. По поводу New(), в юзкейсах у меня 1 New: (func New() *UseCases) внутри которого все абстракции, а методы от него это уже самостоятельные юзкейсы. По поводу New в entity: если у сущности появляется конструктор, значит сущность достойна отдельного пакета. Я его обычно помещаю внутрь entity.
я только разбираюсь в подходах к чистой архитектуре на Go и выражаю огромную благодарность за такое ёмкое и простое объяснение темы (несколько месяцев просто не мог вьехать при самостоятельной реализации). Но есть ряд вопросов: В примере вы указали последовательные инъекции из репозитория в юзкейс, а потом из юзкейса в контроллер, но на диаграммах указано, что юзкейс как отдаёт, так и принимает через интерфейс данные и в репу, и в контроллер. Я правильно понимаю, что из-за формата обратные инъекции не указаны? или нет? если нет, то как конкретно общается контроллер с репой через юзкейс сохраняя подход чистой архитектуры?
21:15 в usecase инджектится repository а потом в controller инджектится usecase, так происходит инверсия зависимостей что нижний слой не зависит от верхних , нижний слой инджектится в верхний. После инджекта слои связываются и спокойно общаются друг с другом по цепочке. request-> controller-> usecase-> repo-> usecase-> controller-> response. То есть не нужно путать связанность кодовой базы и связи слоев в работающей программе.
@@hakooplayplay3212 спасибо! очень хороший ответ. У меня всё встало на свои места год назад(когда вопрос задавал) опытным путём. Переменная(ые) результата вызова метода и являются обратной связью по цепочке. Вроде элементарно, но очевидно только на опыте.
А есть пример проекта по этому принципу с 50к строк кода? У меня в слое юзкейсов уже 10к строк кода и с каждым днем их количество увеличивается, выделять код в функции не получается, потому что тогда функции будут принимать по 10 параметров
Ну так в функции с более чем тремя параметрами нужно передавать структуры. Для каждой функции с большим количеством параметров создаётся input структура, разве нет ?
Может быть нужно сделать дополнительные слои? Тогда зависимости будут везде от центра/центров к внешним слоям домена. Между слоями ставьте интерфейсы, чтобы внутренний слой знал самый минимум о более внешнем, точнее, заказывал только нужный ему функционал, а внешние слои этот функционал обеспечивали. Тогда изменения внешних слоев не затронет внутренний. Если приходится передавать много параметров значит вы не обеспечили принцип low cohesion
@@neprja Отличное видео, спасибо. Но есть вопрос на тему интерфейсов. Интересно ваше мнение. Если мы описываем интерфейсы там, где используем, то что делать, если два или более useCase используют один и тот же репозиторий и одни и те же методы из него? Если с разными методами более менее понятно - можно разделить интерфейс. То с одинаковыми вопрос. Или это уже проблема архитектуры и следует пересмотреть организацию бизнес логики?
@@ИгорьСеверюхин Хороший вопрос. Решение простое - вынести все интерфейсы в отдельный пакет. Раньше я так и делал. Но пришел к тому что структура юзкейсов у меня всегда одна и в неё заинжекчены все адаптеры. А методы этой структуры - это уже конкретные юзкейсы. И интерфейсы я кладу как раз рядом со структурой Usecases в пакет usecase. Получается что интерфейсы находятся в месте использования. Все, кроме 1 интерфейса самого юзкейса (для вызовах в контроллере). Можно было бы держать интерфейс юзкейса в самом контроллере, но контроллеров может быть несколько. Поэтому я нарушаю это правило (держать интерфейс в месте использования) только в этом одном случае.
Привет, Михаил! Очень классный доклад и go-clean-template на гитхабе. Интересно, что нет юнит тестов для repo и webapi, получается, вы их тестируете заодно со слоем usecase. Или в реальных проектах вы пишете тесты для каждого слоя? Спасибо )
В первую очередь хочется тестировать бизнес логику, которая находится в usecase. При тестах usecase мокаются зависимости (repo, webapi, microservice_name). И то тесты пишутся не на каждый usecase. Надо смотреть на ситуацию, есть ли смысл вообще тестировать. Если есть требование на покрытие, тут конечно без вариантов) Но в целом юнитесты пишутся исходя из здравого смысла. Всё остальное покрывают интеграционные тесты.
Михаил, не подскажите, как быть при добавлении новых сущностей, добавлять для каждой свой "класс" обработчика, юзкейса и репозитория или же эти классы будут общими для всех сущностей?
Отталкиватся нужно от юзкейса, новая задача = новый юзкейс. Все остальное вокруг него. Один юзкейс может оперировать несколькими сущностями и несколькими репозиториями в зависимости от задачи. Один юзкейс могут вызвать разные контроллеры (обработчики), их может быть несколько, а может быть один.
@@neprja , можете пожалуйста скинуть какой-нибудь годный репозиторий с чистой архитектурой, где применяется практика с описанием интерфейсов в месте использования ? Очень понравился такой подход, но нигде не могу таких примеров найти.. Глянул в ваш - там вы импорт интерфейсов делаете. Не то чтобы я сам не в состоянии написать код с таким подходом, просто хотелось бы на что-нибудь такое сеньёровское глянуть, где такой подход практикуется :) Ещё, очень желательно, чтобы это было api
Не совсем понял про "у меня use case ни в коем случае не вызывают друг друга". В моем мире это попросту невозможно. Сплошь и рядом новая бизнес-функциональность - это комбинация старой. Типа было яблоко, были креветки, и тут вдруг раз - и появился салат с яблоком и креветками. Как вы в этом случае будете поступать, все свои модули двигать между слоями и папками? Или обратный пример - всё начинается сразу с салата из 50 ингредиентов. Это будет один огромный use case внутри одной папки? А когда потом его части в другой папке понадобятся, как эти части повторно переиспользовать, копированием? Я не критикую, скорее всего это я что-то не так понял. Скорее пытаюсь понять, в чём тут идея. Потому что у меня как раз use case друг друга сплошь и рядом используют, но только через DI, без сильных связей
Давайте от обратного пойдем. Я не скажу как надо, но скажу как не надо. Если у вас один юзкейс вызывает другой юзкейс, то изменение в первом юзкейсе, повлекут изменения во втором. А это вам точно не нужно. Если у вас в одном юзкейсе используется другие юзкейсы, то вы обречены на страдания при минимальных изменениях. Принцип DRY можно забыть. Мартин говорит, что можете расслабится по поводу того что вам кажется что вы просто копируете код. И 2 юзкейса на начальном этапе могут выглядеть абсолютно одинаково. Если это разные юзкейсы их дороги в будущем разойдутся с вероятностью 100%.
@@neprja Я наверное понял. Многое из того, что я для себя считаю юзкейсами, правильнее было бы считать частью доменной модели. Собственно, наверное по этой линии и проходит граница - домен переиспользуется, юзкейс уникален. Спасибо!
Зачем мигать только не понятно. Хочешь слушать человека и одновременно смотреть картинку. Зачем постоянно переключать картинка-человек-картинка, человек объясняет сложный технический вопрос. Рябит в глазах и раздражает, переделать можете по нормальному видео? Чтобы человек без морганий справа, картинка слева, как это делается у нормальных людей. Вроде кодеры, уж это то могли "встроить" в видео, это элементарное юзабилити, чтобы зритель досмотрел доконца, вы же хотите чтобы вас выслушали, верно?
оч много воды. По факту можно все уложить в 5 минут. 1. Есть слои абстракций, они не пересекаются между собой напрямую 2. Используй интерфейс для связи лееров 3. Вот такая структура директорий 4. Вот такой нейминг
Таких пятиминутных выдержек по всей сети море. И ничерта в них не разберёшься без продажи души и рюмок градусов. Я много всего перерыл, но вот это видео - оказалось той самой вишенкой, тем самым последним паззлом, что наконец позволило понять всю картину.
Оратора как-будто пчела в шею укусила. Что это? Красные пятна и волдырик как-будто. Всю дорогу уже не мог нормально слушать о чистой архитектуре, отвлекаясь на эти непонятки. К середине видео краснота прошла, и норм стало слушать.
>>Всю дорогу уже не мог нормально слушать о чистой архитектуре, отвлекаясь на эти непонятки. К середине видео краснота прошла, и норм стало слушать. Это же сарказм, да? Или мне веру в человечество снова терять?
наконец то первое нормальное видео которое прям по полкам про чистую архитектуру на го поясняет, ура, я столько пересмотрел видосов, и нескольок раз прочел мартина чистую архитектуру, но это видео прям глаза открыло
да и на node js это легло отлично!! Просто браво!!
Большое спасибо за объяснение! Особенно с этим кругом было не понятно, а после вашего рисунок все стало на свои места.
Спасибо. Видео несколько раз буду пересматривать .
Спасибо за доклад, очень круто! Есть пару моментов с которыми я не согласен:
12:00 - плохая идея использовать одну структуру в entity на все слои, объясню почему: мне нужно из controller передать в usecase два поля для пагинации (offset, limit). Почему слой entity (слой enterprise бизнес логики) должен знать про какую-то пагинацию?)
14:20 - плохая практика использовать backticks с json в слое entity, т.к этот слой ничего не должен знать о представлении. То есть, если придет заказчик и скажет, что мне вместо json подавай xml, то придется менять слой entity (получается entity и controller имеют какую-то косвенную связь). К тому же у вас могут быть принципиально разные структуры, что в слое entity, что в controller.
Разумеется. Но это уже детали. Я высокоуровнево и доступно старался объяснить.
В реальном мире нужен пакет dto в котором это всё будет находится. Я dto использую для связи controller usecase. Большие и сложные dto бывает доходят и до адаптеров.
Ну и внутри entity постепенно появляются другие пакеты по мере разрастания логики.
Главное понять как управлять сложностью и где проводить границы между разными частями сервиса.
@@neprja а каким образом стоит декаплить пакеты, в случае если мы в юзкейсе реализовали проверку(errors.As, errors.Is) и хендлинг кастомных ошибок(созданных errors.New) , возвращаемых пакетом, отвечающим, например, за интеграцию с другим микросервисом. Мы будем его импортировать, чтобы иметь доступ к переменным и типам тех ошибок. Или есть альтеративный подход, где мы оперируем абстракцией?
О! Не смотря это видео и только начав изучать чистую архитектуру я переделал одно микросервисное приложение под неё. Не знал как лучше архитектурно реализовывать многие вещи (нужна ли отдельная структура для юзкейсов, в ней ли должен храниться репозиторий, где обращаться к другому микросервису) и написал как смог придумать. Сейчас смотрю это видео и понимаю, что почти все делал правильно! Но теперь уже есть точное понимание, зачем и почему так. Спасибо, очень конкретное, дельное и познавательное видео.
Наконец-то кто-то нормально объяснил эту тему
Классный доклад! Очень доходчиво, структурировано и понятно. Спасибо
В рамках микросервисов нет деления на понятние application logic и core business logic. Потому что в самом смысле микросервисов заложено, что микросервисы должны быть слабосвязаны между собой, а соответственно и сквозных данных/логики между ними должно быть по минимуму.
Это разделение было для стандартных монолитов, и за счет этого разделения возможно было бы использовать один единый удобный слой core business logic для разных целевых модулей/блоков приложения. Например, одна модель счет фактуры для разных сценариев и интерфейсов использования: наборщик на складе, водитель-экспедитор, приемщик и т.д. Они работают каждый через свой слой абстракции(application logic) с одной общей моделью(core business logic).
В архитектуре микросервисов это спокойно распиливается на 4(условно) микросервиса.
Спасибо за видео. Очень многое понятно. Но хочется для таких как я 😂(начинающих), объяснить все тоже самое , но на примере конкретного приложения , например файлообменник. И прям на нем показать данный подход
19:17 Разве в импортах не должно быть хотя бы импорта моделей/entity?
Классное объяснение! Заберу к себе пару тезисов - у меня на канале реализация чистой архитектуры в 3 частях.
Огонь! Спасибо большое!
Подскажите, а как быть, если нужно в одном юзкейсе вызвать методы другого юзкейса ( в apple дернуть метод, связанный с banana)?
странно что WebAPI оказался в слое Infrastructure, хотя это обычно находится в слое Presentation
Тоже никогда не понимал, зачем нужно пилить столько dtoшек в рамках микросервиса, особенно при том что всё это делается в папке internal, т.е. переиспользование всего этого добра в других проекта не предполагается...
По мне так dto в такой архитектуре должен быть аналогом адаптера типов. Т.е. если вместо одного из модулей или вместо одной из частей системы мы подключаем внешний пакет, который не умеет работать с нашими моделями. В таком случае мы как раз используем dto, чтобы произвести маппинг на нужный формат данных. Но если мы все пилим в локальных, закрытых, не нацеленных на переиспользование в других проектах модулях - нафига этот огород?
Прокидывать везде единые модели данных - это нормально. Но при этом если потом понядобится/захочется ввести локальные dto для каких-то сервисов/модулей - это можно легко сделать точечно.
Конечно же все вшесказанное работает, если dto и entity совпадают на 90+%. Когда мы там передаем кучу служебных данных, не связанных с моделями - ну тут уж никуда.
На 2 скорости становится нормально)
Такс стоп, вы в докладе рассказали что должен быть модуль infrastucture где находяться repo и webapi. А в репе они у вас в usecase находяться.
Репа немного устарела. Руки никак не доходят обновить. То что в докладе - актуально.
@@neprja Благодарю за ответ
тот же вопрос был))) спасибо!!!
@@neprja а можете обновить реп пожалуйста?
Немного не согласен. Во-первых, нет смысла отделять интерфейсом слой контроллеров от слоя UseCase, т.к. UseCase никогда не будет вызывать контроллер, а контроллер вполне имеет право быть в курсе про конкретный UseCase согласно той же диаграмме зависимостей. Ситуации, конечно, разные могут быть, но в принципе это не нужно. И во-вторых, entity могут использоваться по всему проекту по той же причине. DTO никто не отменял, но, это, скорее элемент абстракции, а не ограничения видимости.
Да, согласен)
Спасибо!
красава
А могли бы разъяснить в чём отличия кроме названий слоёв между Clean и Hexagonal, Onion архитектурами?
Отличий особо нет. Все они об одном и том же.
@@neprja простите за глупые вопросы, я ещё даже не джун. У вас хорошая слоистость, поэтому пока не просто сразу въехать. Я верно понял, что ваш слой controller это слой port в гексагоналке?
@@yarbersheer8559 Да. Контроллер - это точка входа.
@@neprja спасибо) а могу ещё отнять немного вашего времени вопросом.
Часто вижу, что параметры среды не выносятся в отдельный сервис синглтоном, при этом очевидно, что эта функция может иметь несколько итераций построения объекта среды, например default -> flags -> env -> external file (yaml, toml etc).
Почему не принято выносить эту процедуру в отдельный entity? Или просто обычно этому нет нужды уделять отдельного внимания?
@@yarbersheer8559 В entity ему точно не место, entity - это сущность бизнес-логики. А параметры среды - это конфигурация для построения объектов архитектуры приложения. Лучшая практика для переменных - делать синглтоном.
Хмм, а как в вашем случае (на 25:50 показано справа) предполагается писать одни и те же методы (`New()`, например) для разных юзкейсов (apple/banana) в одном пакете usecase? Всё-таки надо их делить (создавать подпапки apple/banana внутри usecase) или есть возможность разграничить scope файлов apple/banana, чтобы компилятор не ругался на одинаковые методы?
Просто если делить юзкейсы по папкам, тогда инфраструктуру, кажется, нужно выносить в отдельный пакет вне usecase, т.к. её могут использовать несколько юзкейсов (в репозитории из примера инфра лежит внутри usecase)
Спасибо за замечания) На счет репозитория из примера, он немного устарел, туда лучше не смотрите. Идеи со слайдов актуальны. У меня пакет infrastructure находится на одном уровне с controller, entity и usecase. По поводу New(), в юзкейсах у меня 1 New: (func New() *UseCases) внутри которого все абстракции, а методы от него это уже самостоятельные юзкейсы. По поводу New в entity: если у сущности появляется конструктор, значит сущность достойна отдельного пакета. Я его обычно помещаю внутрь entity.
я только разбираюсь в подходах к чистой архитектуре на Go и выражаю огромную благодарность за такое ёмкое и простое объяснение темы (несколько месяцев просто не мог вьехать при самостоятельной реализации). Но есть ряд вопросов: В примере вы указали последовательные инъекции из репозитория в юзкейс, а потом из юзкейса в контроллер, но на диаграммах указано, что юзкейс как отдаёт, так и принимает через интерфейс данные и в репу, и в контроллер. Я правильно понимаю, что из-за формата обратные инъекции не указаны? или нет? если нет, то как конкретно общается контроллер с репой через юзкейс сохраняя подход чистой архитектуры?
21:15 в usecase инджектится repository а потом в controller инджектится usecase, так происходит инверсия зависимостей что нижний слой не зависит от верхних , нижний слой инджектится в верхний. После инджекта слои связываются и спокойно общаются друг с другом по цепочке. request-> controller-> usecase-> repo-> usecase-> controller-> response. То есть не нужно путать связанность кодовой базы и связи слоев в работающей программе.
@@hakooplayplay3212 спасибо! очень хороший ответ. У меня всё встало на свои места год назад(когда вопрос задавал) опытным путём. Переменная(ые) результата вызова метода и являются обратной связью по цепочке. Вроде элементарно, но очевидно только на опыте.
Спасибо.
А есть пример проекта по этому принципу с 50к строк кода? У меня в слое юзкейсов уже 10к строк кода и с каждым днем их количество увеличивается, выделять код в функции не получается, потому что тогда функции будут принимать по 10 параметров
Ну так в функции с более чем тремя параметрами нужно передавать структуры.
Для каждой функции с большим количеством параметров создаётся input структура, разве нет ?
Совсем по верхам - ваша проблема в протекании модели в слой юзкейса
Может быть нужно сделать дополнительные слои? Тогда зависимости будут везде от центра/центров к внешним слоям домена. Между слоями ставьте интерфейсы, чтобы внутренний слой знал самый минимум о более внешнем, точнее, заказывал только нужный ему функционал, а внешние слои этот функционал обеспечивали. Тогда изменения внешних слоев не затронет внутренний.
Если приходится передавать много параметров значит вы не обеспечили принцип low cohesion
интерфейсы нужно размещать там, где используются - об этом не нужно думать :)
По дефолту, да.
@@neprja Отличное видео, спасибо. Но есть вопрос на тему интерфейсов. Интересно ваше мнение. Если мы описываем интерфейсы там, где используем, то что делать, если два или более useCase используют один и тот же репозиторий и одни и те же методы из него?
Если с разными методами более менее понятно - можно разделить интерфейс. То с одинаковыми вопрос.
Или это уже проблема архитектуры и следует пересмотреть организацию бизнес логики?
@@ИгорьСеверюхин Хороший вопрос.
Решение простое - вынести все интерфейсы в отдельный пакет.
Раньше я так и делал. Но пришел к тому что структура юзкейсов у меня всегда одна и в неё заинжекчены все адаптеры. А методы этой структуры - это уже конкретные юзкейсы.
И интерфейсы я кладу как раз рядом со структурой Usecases в пакет usecase. Получается что интерфейсы находятся в месте использования. Все, кроме 1 интерфейса самого юзкейса (для вызовах в контроллере). Можно было бы держать интерфейс юзкейса в самом контроллере, но контроллеров может быть несколько. Поэтому я нарушаю это правило (держать интерфейс в месте использования) только в этом одном случае.
@@ИгорьСеверюхин , а разве это такая большая проблема ? Меня это вполне устраивает
Балдеж
Привет, Михаил! Очень классный доклад и go-clean-template на гитхабе. Интересно, что нет юнит тестов для repo и webapi, получается, вы их тестируете заодно со слоем usecase. Или в реальных проектах вы пишете тесты для каждого слоя? Спасибо )
В первую очередь хочется тестировать бизнес логику, которая находится в usecase. При тестах usecase мокаются зависимости (repo, webapi, microservice_name). И то тесты пишутся не на каждый usecase. Надо смотреть на ситуацию, есть ли смысл вообще тестировать. Если есть требование на покрытие, тут конечно без вариантов) Но в целом юнитесты пишутся исходя из здравого смысла. Всё остальное покрывают интеграционные тесты.
Ну хоть кто-то снизошел до уровня имплементации и четких примеров вместо бесконечных абстракций
Хорошо, что человек решил помочь разобраться в теме. Но изложение путанное и местами сумбурно.
Совсем не понял про пустые import. Если usecase, к примеру, возвращает структуру entity то без импорта никак не обойтись. Разве нет?
Михаил, не подскажите, как быть при добавлении новых сущностей, добавлять для каждой свой "класс" обработчика, юзкейса и репозитория или же эти классы будут общими для всех сущностей?
Отталкиватся нужно от юзкейса, новая задача = новый юзкейс. Все остальное вокруг него. Один юзкейс может оперировать несколькими сущностями и несколькими репозиториями в зависимости от задачи. Один юзкейс могут вызвать разные контроллеры (обработчики), их может быть несколько, а может быть один.
@@neprja Спасибо.
@@neprja , можете пожалуйста скинуть какой-нибудь годный репозиторий с чистой архитектурой, где применяется практика с описанием интерфейсов в месте использования ? Очень понравился такой подход, но нигде не могу таких примеров найти.. Глянул в ваш - там вы импорт интерфейсов делаете. Не то чтобы я сам не в состоянии написать код с таким подходом, просто хотелось бы на что-нибудь такое сеньёровское глянуть, где такой подход практикуется :) Ещё, очень желательно, чтобы это было api
Не совсем понял про "у меня use case ни в коем случае не вызывают друг друга". В моем мире это попросту невозможно. Сплошь и рядом новая бизнес-функциональность - это комбинация старой. Типа было яблоко, были креветки, и тут вдруг раз - и появился салат с яблоком и креветками. Как вы в этом случае будете поступать, все свои модули двигать между слоями и папками?
Или обратный пример - всё начинается сразу с салата из 50 ингредиентов. Это будет один огромный use case внутри одной папки? А когда потом его части в другой папке понадобятся, как эти части повторно переиспользовать, копированием?
Я не критикую, скорее всего это я что-то не так понял. Скорее пытаюсь понять, в чём тут идея. Потому что у меня как раз use case друг друга сплошь и рядом используют, но только через DI, без сильных связей
Давайте от обратного пойдем. Я не скажу как надо, но скажу как не надо. Если у вас один юзкейс вызывает другой юзкейс, то изменение в первом юзкейсе, повлекут изменения во втором. А это вам точно не нужно. Если у вас в одном юзкейсе используется другие юзкейсы, то вы обречены на страдания при минимальных изменениях. Принцип DRY можно забыть. Мартин говорит, что можете расслабится по поводу того что вам кажется что вы просто копируете код. И 2 юзкейса на начальном этапе могут выглядеть абсолютно одинаково. Если это разные юзкейсы их дороги в будущем разойдутся с вероятностью 100%.
Креветки и яблоки - это entity или абстракции (infrastructure), а в юзкейсах вы их отдаете либо не изменными, либо готовите из них разные салаты.
@@neprja Я наверное понял. Многое из того, что я для себя считаю юзкейсами, правильнее было бы считать частью доменной модели. Собственно, наверное по этой линии и проходит граница - домен переиспользуется, юзкейс уникален. Спасибо!
@@RusRes Верно
Зачем мигать только не понятно. Хочешь слушать человека и одновременно смотреть картинку. Зачем постоянно переключать картинка-человек-картинка, человек объясняет сложный технический вопрос. Рябит в глазах и раздражает, переделать можете по нормальному видео? Чтобы человек без морганий справа, картинка слева, как это делается у нормальных людей. Вроде кодеры, уж это то могли "встроить" в видео, это элементарное юзабилити, чтобы зритель досмотрел доконца, вы же хотите чтобы вас выслушали, верно?
Учтем
Доклад классный, а вот того кто делал монтаж - пороть розгами. Показывают код, он переключает на докладчика. Homo Idiotus.
оч много воды. По факту можно все уложить в 5 минут.
1. Есть слои абстракций, они не пересекаются между собой напрямую
2. Используй интерфейс для связи лееров
3. Вот такая структура директорий
4. Вот такой нейминг
Таких пятиминутных выдержек по всей сети море. И ничерта в них не разберёшься без продажи души и рюмок градусов. Я много всего перерыл, но вот это видео - оказалось той самой вишенкой, тем самым последним паззлом, что наконец позволило понять всю картину.
Оратора как-будто пчела в шею укусила. Что это? Красные пятна и волдырик как-будто. Всю дорогу уже не мог нормально слушать о чистой архитектуре, отвлекаясь на эти непонятки. К середине видео краснота прошла, и норм стало слушать.
От волнения)
да уж )) неспортивный пацан какойто
>>Всю дорогу уже не мог нормально слушать о чистой архитектуре, отвлекаясь на эти непонятки. К середине видео краснота прошла, и норм стало слушать.
Это же сарказм, да? Или мне веру в человечество снова терять?