1-й в Украине сертификационный курс по UX от UXQB — крупнейшего в мире комьюнити UX специалистов
×Закрыть

Сервисы и их зависимости

Допустим, есть сервис S1, он делает какие-то операции с какой-то сущностью, т.е. он зависит от неё, пусть это будет D1. Теперь появилась необходимость в методе, который работает с D2. Можно создать сервис S2. Точно также сервис S3 с зависимостью D3. Но далее может оказаться, что нам необходим сервис, который работает одновременно и с D1, и с D2. Можно наплодить 100500 сервисов всевозможных комбинаций, но, во-первых, возможно они будут иметь пересекающийся функционал (а то и идентичный), а во-вторых, с ними будет неудобно работать их клиентам.

Заметил, что всегда реализовывал эту проблему «в лоб», делал один большой сервис с множеством зависимостей, как-то не придавал этому значения. И поймал себя на мысли, что не пойму, как это правильно реализовать. Любые решения, что мне приходят на ум, мне не нравятся. Разве что если реализовывать это наследованием, чтобы взять функционал от базового сервиса и расширить его с новой зависимостью, но тогда нужно менять подход с фиксацией данных (например, если это БД, то внесение самих изменений вынести в отдельный метод), плюс ко всему в .NET (и в Java, насколько я знаю) нет множественного наследования, т.е. взять базовый функционал от нескольких сервисов не получится...

LinkedIn
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

1 сущность = 1 сервис. S3 будет дергать S1 и S2 для работы с D1 и D2 соответственно. Надо смотреть на примере.

в самом примитивном случае, когда у тебя есть s1 с д1 и d2 с d2, и понадобилось чтобы был s3 с d1 и d2 то вероятно есть косяк в разделении ответственности между сервисами, либо d1 и d2 состоявяют одно целое, которое зачем-то разбито на два

в более запущеных случаях может понадобиться сделать внутреннее апи между сервисами

если у тебя есть желание следовать правилу «один сервис — одна сущность», то это гарантированно достижимо

Конвеєр зі своїх сервісів запили, і хай вони собі там обробляють що можуть

А так нема тут «правильного» і «кращого» підходу. Це ж реальний світ, а не книги.
Те, що немає наслідування від багатьох класів не проблема, є композиція. Але це ж буде «двоповерховий» рівень сервісів, типу прості сервіси і суперсервіси. Можна вигадувати різні класи-операції, валідатори, специфікації, які реюзати з різних сервісів. Це вже оод, який не втиснутий в аксіоми будь-якої настольної книги про патерни )

При анемичном подходе к моделированию бизнес логики избавляться от дубликатов непростое занятие — часто с этим приходиться мириться раз уже выбрали более простой подхода к написанию бизнес логики. Но даже в реализации rich подхода часто встречается сервисный уровень для Dal того же. Важно разделять и понимать что вы хотите, иметь как можно более простые и понятные конвенции по уровням абстракции для команды.

Та rich domain model навіть більш незручна, як тільки операція з двома рівноправними не master-detai entity, все, гудбай rich model, велкам сервіс.

Вот для этого и придумали REST. Очень мало кто знает на кой хер ему поклоняются, но миллион леммингов не могут ошибаться. Ссылаясь на этот идол, ты как и раньше будешь плодить 100500 сервисов, но теперь это будешь называть не авгиевы конюшни, а RESTful.

Я лишь о принципе. Лучше наплодить сотню-другую простеньких контроллеров бекенда, чем пытаться делать универсальное неповоротливое говно. Почему так: дешевизна сопровождения и изменения. Когда сервисы мало зависят друг от друга, тебе не проблема что-то поменять, например принципы их создания, алгоритмы безопасности, и т.д и т.п, и при этом не париться что старые сервисы и все задачи что на них завязаны — внезапно перестанут работать.

А потом в продакшне обнаруживается, что ты поменял контракт какого-то сервиса, и теперь не работает часть юзер сторис. Ну там нотификации отсылаются не в том порядке, как раньше, к примеру.

а у Вас покрыты 100% реальных сценариев)

Как минимум брэйк контракта о котором Вы выше писали))

Почему Вы так уверены)
Потому что на проекте никогда не было багов, не отловленных тестами и ушедших в продакшн?

По моему, Вы путаете тёплое с мягким.))

наплодить сотню-другую простеньких контроллеров бекенда

И потом очень радуешься когда надо вносить изменения и тебе надо передеплоивать 50 из них.

Бывало. Часов 8 убил, когда потребовалось не только передеплоить, а ещё и перекомпилить все зависимые сервисы, благо зависимые пока ещё были в пределах досягаемости. Вот только ПРИЧИНА была не в «надо», а в «мудромбля» решении руководства, которое, как общеизвестно, никогда не ошибается.

Через три дня решение было передеплоить всё обратно, и уже в аврале — нашли критичный баг, который не ловили тесты, ибо он был за пределами компонента, но утыкался в прикладной софт написанный говнокодерами методом тыка, не глядя на документацию API.

Ещё через день исправил баг и задеплоил всё обратно в одно рыло, руководству не докладывая, но общаясь с саппортом и работниками с софтом. Только поэтому оно работает, может даже до сих пор. Мораль: «покрытие» кода тестами не работает, имейте бета-тестеров.

звучит как у вас должен быть сервис для выполнения базовой функционвальности (примеры: БД, системы очередей) — но вопрос в том что вы в это вкладываете?

нет базовой функциональности для всех сервисов. Может быть, образно говоря, базовая для S1 и S2, но не для остальных, и аналогично, базовая для S3 и т.д.....

KISS большая/малая связность. Пока проект маленький — можно писать монолитом. Когда становится нереально большим — выносим из него один или группу сервисов, функционал которых почти не пересекается с остальными сервисами. Получаем 2 отдельных не таких больших монолита. Повторяем. Получаем микросервисы. Собственно, так их и рекомендовали делать. martinfowler.com/bliki/MonolithFirst.html

это всё понятно, но на практике не выходит каменный цветок...

И поймал себя на мысли, что не пойму, как это правильно реализовать. Любые решения, что мне приходят на ум, мне не нравятся.

Так будет почти всегда. Идеальной архитектуры нет, за все надо платить. Особенно если проект дописывается, постепенно наращивая функционал.

да, но я тут с нуля не пойму, как правильно построить, чтобы было гибко

Гибко это далеко не всегда хорошо

тогда опиши свою задачу в деталях, если не под NDA. В мире существует под сотню архитектурных подходов как раз потому, что ни один из них не подходит для любой задачи.

В PHP есть Traits, которые по сути подмешивают методы другого «класса» внутрь любого, это отчасти решает проблему необходимости мульти-наследования. Выглядит вот так: gist.github.com/...​314af394ade433a061ea80d02

Имхо, то, что вы описали, лежит в идее микросервисов, когда они все равно независимые, и общаются каким-то образом друг с другом по АПИ в любом виде (через контейнеры DI, медиатор, по REST/RPC/etc).

В общем, все как обычно — нужны реальные примеры, чтобы понять, что лучше всего использовать :)

зачем примеры, вопрос то абстрактный...

Судя по всем вашим ответам — вы говорите про сферического коня. Ожидаете получить конкретный ответ на абстрактный вопрос?
Ваш ответ — микросервисы и общение между ними или медиатор.

нет множественного наследования, т.е. взять базовый функционал от нескольких сервисов не получится

інтерфейси?

как интерфейсы помогут с наследованием базового функционала?

если у вас операции одинаковые, но надо работать с разными сущностями(ваши D1 и D2) то вы выделяете общие черты в интерфейс I0 и ваш единственный сервис работает только с интерфейсом, не заморачиваясь, это D1 или D2

нет, операции разные. И их «комбинации» тоже разные.

возможно они будут иметь пересекающийся функционал (а то и идентичный),
нет, операции разные. И их «комбинации» тоже разные.

странно как-то

Подписаться на комментарии