А как ещё? В ImportService можно дописывать логику, которую относим к предметной области. В реализации, в Mapper, например, можно вызвать другие сервисы, относящиеся к предметной области. В общем, ещё много всего можно доделывать.
Если в результате вашего примера получилось что-то, что делать нецелесообразно - это не наглядный пример.
В каких-то случаях это может быть целесообразным. Как наглядный пример связан с целесообразностью?
А зачем он нужен?
Зачем выделять предметную область? Об этом есть множество книг и статей. Похоже вы не в теме, и вам следовало бы ознакомиться с материалом. Если вам это не нужно, пройдите мимо, и не выносите мозг людям, пожалуйста. На остальное даже не хочу отвечать.
Да много где разъяснено. И в этой статье, указано, что мы получили класс, куда можно выделить логику приложения, бизнес-логику. Получили отдельный компонент импорта, который можно повторно использовать в пределах проекта или во многих проектах. Принцип DRY (Don't repeat yourself). Избегаем дублирование логики, что облегчает поддержку проекта. Отделяем основную логику от вторичной.
Простой пример, Security компонент Symfony. Вы берёте его и переиспользуете, прописываете конфиги, кастомизируете по необходимости, и не нужно в каждом проетке с нуля писать логику связанную с авторизацией.
Но есть, конечно, и минус в том, что такой компонент нужно поддерживать, это время, ресурс. Ну и потребуется изучать этот компонент перед использованием. Поэтому нужно взвешивать плюсы и минусы, и думать в какой мере применять те или иные практики в конкретном случае.
Писать компонент импорта, поддерживать его, мне кажется нецелесообразным в большинстве случаев. Но он взят просто как наглядный пример.
Уж вы то всё знаете, кому что нужно. Статья про реализацию. Про теорию есть другие статьи. Многие знают про SOLID, но понять и применить его довольно сложно, и я думаю, эта статья многим может быть полезна. Здесь один из вариантов реализации, а разных вариантов может быть много.
Неужели не понятно, что не получилось сразу нормально отформатировать текст в редакторе хабра. Сложность выставлена в соответствии с рекомендациями Хабра. Сразу ссылка на гитхаб? Зачем?
Зачем идти дальше? Объясните читателю что не так с первой версией реализации
Статья про реализацию SOLID. То есть, первая версия не соответствует SOLID. Неужели это не понятно?
Да, соглашусь, всегда применять описанные практики не стоит, лучше делать это выборочно. Иначе код будет переусложнён, много лишнего кода придётся писать.
Высшая математика тоже сложная для понимания, зачем она... (ирония). Все относительно, если для вас текст слишком сложный, вы можете его не читать, никто не заставляет.
В книге "Чистая архитектура", как раз и приводится один из примеров, где в Service хранится бизнес-логика. Директория не всегда должна соответствовать какой-то конкретной задаче, не выдумывайте.
Положить можно куда угодно, я для примера взял App\Service. Да, в основном код можно класть рядом, туда же. Но, например, удобно видеть все точки входа в приложение, открыв App\Controller. С EventListener систуация неоднозначная, думаю, можно и рядом с сервисом хранить. Если же entity хранить рядом с сервисом, придётся прописывать их в конфиге для каждого модуля, что не очень удобно, да и maker создает классы в App\Entity. Можно, конечно, с этим что-то придумать, но это уже отдельная тема. Да и вопрос, стоит ли? Если следовать правилу, что первый уровень в Entity, Repository и т.д. это название модуля, то проблемы быть не должно. То есть Entity\Module1, Repository\Module1 и т.д.
Можно рассматривать первый уровень в App, как некоторые адаптеры к фреймворка к логике приложения.
Еще, как вариант, делить приложение на бандлы, как делалось в старых версиях Symfony. В общем-то неплохой вариант, но добавляются некоторые издержки на поддержку бандлов. Но, конечно, не такие, как на поддержку микросервисов. Бандл, если нужно, можно всегда доработать до микросервиса. Да и микросервис то к чему? Можно же запустить два инстанса приложения на разных серверах. Что даст микросервис, сэконмит несколько мегабайт оперативной памяти? Делать отдельные сервисы есть смысл в довольно редких случаях.
А книги на тему DDD это вообще, больше похоже на какой-то бизнес-тренинг, секту, чем на техническую литературу. Не даром, есть сокращенные до брошюры книги на эту тему, но и в них полезной информации мало, если ее вообще можно так назвать.
А можно не выносить в другие классы с разными названиями? Этот совет ничего полезного вообще не несём.
Можно выносить, можно не выносить, это решает разработчик. Я предлагаю вариант, который вижу подходящим, чтобы следовать SOLID.
Можете раскрыть мысль? Как я вместо интерфейса могу DTO использовать? Какие некоторые другие минусы?
Создаёте DTO, и переносите в нее данные из сущности. В это минусы - создание нового экземпляра, необходимость переноса данных. В классе сущности не видно связи с DTO, в отличие от интерфейса. Интерфейс более гибок, можно создать DTO, реализующий интерфейс, если нужно.
Очень общая фраза, которая никак не следует из предыдущих рассуждений и непонятно при чём тут SRP.
В сущности, в таблице БД могут быть разнородные данные. И логика их обработки разносится по разным классам - сервисам. В этом и применение SRP.
О какой конкретно логике речь?
О логике обработки данных сущности, о логике приложения, какой же еще?
Этот принцип тут ни при чём вообще, я вполне могу туда подсунуть реализацию, нарушающую принцип.
Это каким образом? Если вы не правите оригинальный код, а наследуетесь, принцип соблюдается.
Пустые слова, ибо нет конкретных аргументов
Код разделен на самостоятельные части, соответственно их можно разрабатывать более независимо и проще поддерживать. Какие еще нужны аргументы?
Вот тут я вообще запутался, я пытался понять пример, но не осилил. Наш сервис получается ходит и вверх и вниз? Обычно направление выполнения должно как то в одну сторону идти.
Да, может ходить вверх и вниз. Вниз ходит через инверсию зависимости, чтобы не зависеть от нижних уровней.
А как ещё? В ImportService можно дописывать логику, которую относим к предметной области. В реализации, в Mapper, например, можно вызвать другие сервисы, относящиеся к предметной области. В общем, ещё много всего можно доделывать.
ImportService зависит только от ImporterInterface. А за этим интерфейсом уже детали реализации.
Первые попавшиеся определения SRP:
Здесь, в коде, отдельно Mapper, Receiver и т.д.
Что-то вы путаете. Здесь данные получаем одним запросом к api, а обрабатываем в цикле.
В каких-то случаях это может быть целесообразным. Как наглядный пример связан с целесообразностью?
Зачем выделять предметную область? Об этом есть множество книг и статей. Похоже вы не в теме, и вам следовало бы ознакомиться с материалом. Если вам это не нужно, пройдите мимо, и не выносите мозг людям, пожалуйста. На остальное даже не хочу отвечать.
Да много где разъяснено. И в этой статье, указано, что мы получили класс, куда можно выделить логику приложения, бизнес-логику. Получили отдельный компонент импорта, который можно повторно использовать в пределах проекта или во многих проектах. Принцип DRY (Don't repeat yourself). Избегаем дублирование логики, что облегчает поддержку проекта. Отделяем основную логику от вторичной.
Простой пример, Security компонент Symfony. Вы берёте его и переиспользуете, прописываете конфиги, кастомизируете по необходимости, и не нужно в каждом проетке с нуля писать логику связанную с авторизацией.
Но есть, конечно, и минус в том, что такой компонент нужно поддерживать, это время, ресурс. Ну и потребуется изучать этот компонент перед использованием. Поэтому нужно взвешивать плюсы и минусы, и думать в какой мере применять те или иные практики в конкретном случае.
Писать компонент импорта, поддерживать его, мне кажется нецелесообразным в большинстве случаев. Но он взят просто как наглядный пример.
Уж вы то всё знаете, кому что нужно. Статья про реализацию. Про теорию есть другие статьи. Многие знают про SOLID, но понять и применить его довольно сложно, и я думаю, эта статья многим может быть полезна. Здесь один из вариантов реализации, а разных вариантов может быть много.
Неужели не понятно, что не получилось сразу нормально отформатировать текст в редакторе хабра. Сложность выставлена в соответствии с рекомендациями Хабра. Сразу ссылка на гитхаб? Зачем?
Статья про реализацию SOLID. То есть, первая версия не соответствует SOLID. Неужели это не понятно?
Да, соглашусь, всегда применять описанные практики не стоит, лучше делать это выборочно. Иначе код будет переусложнён, много лишнего кода придётся писать.
Можно и в Service все складывать, большой разницы нет на самом деле. Но тогда действительно эта директория будет лишней. Я уже объяснял в комментарии выше https://habr.com/ru/articles/736574/#comment_25576836
Высшая математика тоже сложная для понимания, зачем она... (ирония). Все относительно, если для вас текст слишком сложный, вы можете его не читать, никто не заставляет.
В книге "Чистая архитектура", как раз и приводится один из примеров, где в Service хранится бизнес-логика. Директория не всегда должна соответствовать какой-то конкретной задаче, не выдумывайте.
Это почему статья не конструктивна?
Положить можно куда угодно, я для примера взял App\Service. Да, в основном код можно класть рядом, туда же. Но, например, удобно видеть все точки входа в приложение, открыв App\Controller. С EventListener систуация неоднозначная, думаю, можно и рядом с сервисом хранить. Если же entity хранить рядом с сервисом, придётся прописывать их в конфиге для каждого модуля, что не очень удобно, да и maker создает классы в App\Entity. Можно, конечно, с этим что-то придумать, но это уже отдельная тема. Да и вопрос, стоит ли? Если следовать правилу, что первый уровень в Entity, Repository и т.д. это название модуля, то проблемы быть не должно. То есть Entity\Module1, Repository\Module1 и т.д.
Можно рассматривать первый уровень в App, как некоторые адаптеры к фреймворка к логике приложения.
Еще, как вариант, делить приложение на бандлы, как делалось в старых версиях Symfony. В общем-то неплохой вариант, но добавляются некоторые издержки на поддержку бандлов. Но, конечно, не такие, как на поддержку микросервисов. Бандл, если нужно, можно всегда доработать до микросервиса. Да и микросервис то к чему? Можно же запустить два инстанса приложения на разных серверах. Что даст микросервис, сэконмит несколько мегабайт оперативной памяти? Делать отдельные сервисы есть смысл в довольно редких случаях.
А книги на тему DDD это вообще, больше похоже на какой-то бизнес-тренинг, секту, чем на техническую литературу. Не даром, есть сокращенные до брошюры книги на эту тему, но и в них полезной информации мало, если ее вообще можно так назвать.
Для такого лучше использовать Stimulus
Если вы откроете другую литературу по схожей теме, в том числе книгу "Чистая архитектура", то очень удивитесь, что там практически нет кода.
Множество литературы об этом есть. Думаю, вам никто не будет здесь её пересказывать.
Если вы не понимаете написанного, видимо, вам оно не нужно.
В программировании это уже устоявшееся слово, имеет отношение к проектированию.
Можно выносить, можно не выносить, это решает разработчик. Я предлагаю вариант, который вижу подходящим, чтобы следовать SOLID.
Создаёте DTO, и переносите в нее данные из сущности. В это минусы - создание нового экземпляра, необходимость переноса данных. В классе сущности не видно связи с DTO, в отличие от интерфейса. Интерфейс более гибок, можно создать DTO, реализующий интерфейс, если нужно.
В сущности, в таблице БД могут быть разнородные данные. И логика их обработки разносится по разным классам - сервисам. В этом и применение SRP.
О логике обработки данных сущности, о логике приложения, какой же еще?
Это каким образом? Если вы не правите оригинальный код, а наследуетесь, принцип соблюдается.
Код разделен на самостоятельные части, соответственно их можно разрабатывать более независимо и проще поддерживать. Какие еще нужны аргументы?
Да, может ходить вверх и вниз. Вниз ходит через инверсию зависимости, чтобы не зависеть от нижних уровней.
Интерфейс - часть бизнес-логики, сама фабрика - часть инфраструктуры