Как стать автором
Обновить

Комментарии 30

А еще registerClient упадет, если упали на маппинге или не удалось достучаться до Кафки, хотя сама регистрация клиента была успешно выполнена. Впрочем, это тема уже для другой статьи.

И что здесь неправильно?

Мне кажется, потребителю сервиса надо знать, что регистрация клиента прошла или нет, а не то, отправил ли сервис что-то куда-то. Потому что если сервис регистрации упал с ошибкой, то потребитель попробует повторить регистрацию, но в этот раз у него не получится, так как клиент уже зарегистрирован, просто потребитель не в курсе.

То есть сервис должен падать только при невозможности выполнения его основной функции - регистрации, а все сопутствующие действия либо проводить без прокидывания exception наверх, либо, если это важно, откатывая регистрацию. Тогда у потребителя будет четкое понимание: выполнилось успешно - значит регистрация прошла; exception - значит регистрации не случилось.

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

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

Лисков пришла откуда не ждали

Ну вот у вас-же наполовину уже сделано по-человечески. Детали реализации сохранения в базу вынесены в ClientRepository. Почему-же и с очередью сообщений вся логика и dependency зашита в RegistrationService?

Вынесите детали реализации отправки сообщений в отдельный репозиторий MessageRepsitory с определенным интерфейсом и кидайте сообщения оттуда. С помощью какого механизма -Кафка, кролика или еще чего, это не должно касаться сервиса. Надо будет - выкинете кафку, поставите рэббита.

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

>Надо будет - выкинете кафку, поставите рэббита.

Если нада будет, то придет задача и мы внесем правки в сервис. Нет ровно ни одной причины пытаться угадать, что там будет завтра и под это закладываться. Это ничем не лучше попытки гадания на таро.

По человечески, это вот так: https://ru.wikipedia.org/wiki/SOLID_(%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5)

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

SOLID, точнее, идеология Дяди Боба - это практически, промышленный стандарт организации кода.

Если уж мы начали говорить на языке эмпирических принципов, то невозможно пройти мимо старых добрых KISS и YAGNI. И вот тут хочется задать вам вопрос: а на чем основана ваша уверенность, что предложенное решение действительно необходимо? Это что, принцип ради принципа? Или, может, дизайн ради дизайна? Звучит как попытка украсить ёлку гирляндами там, где нужно просто подключить лампочку.

SOLID, точнее, идеология Дяди Боба - это практически, промышленный стандарт организации кода.

Удивительно, что в 2024 ещё находятся люди, которые этому верят, несмотря на всю практику и множество обоснованных (в отличие от) критических статей; несмотря на то, что Clean Code противоречит сама себе и предлагает ужасный код; несмотря на то, что есть множество более внятно формулированных и потому более реальных методик... которые ещё и работают.

SOLID же в основе неконкретен настолько, насколько это вообще может быть. 'S' просто непонятно в отрыве от любой реальности, и становится понятным только через конкретные требования вроде Information Expert из GRASP (более внятный набор принципов) и реалии конкретного требования к гибкости и тестировании - но "дядя Боб" об этом не скажет, напустив туману. 'O' вообще не имеет отношения к проектированию, оно про жизненный цикл с развитием. 'L' про стабильность интерфейсов (в самом широком смысле) и контрактов. Остальные два имеют смысл только в одной конкретной объектной модели и теряются при выходе за её пределы.

На самом деле смысл этого симулякра совсем другой: это выдача - для внешнего потребителя, которыми являются непрограммирующие менеджеры и прочее начальство - hard skills за soft skills. Используя стандартизованные термины из SOLID или паттернов GoF, программист может объяснять начальству проблемы на стандартизованном языке, который, благодаря шуму, оно уже знает и предполагает его услышать. Но это же загоняет программиста в прокрустово ложе разработки именно в этих понятиях - которое работает, в основном, в домене "внутреннего софта" по Спольски, где и сконцентрировано основное начальственное невежество. Так что в целом оно скорее позитивно. Но - именно для программистов я бы желал, чтобы они понимали, насколько всё это чистейший симулякр.

за сколько лет работы ни разу не приходилось объясняться терминами SOLID с непрогоаммистами. зачем вы вообще кому-то не коллеге рассказываете что-то подобное? по солид, а можете показать проект, который не использует эти принципы, поддерживается и развивается достаточно долго вменяемым количеством разработчиков, при этом каждое изменение это не переписать 70% кода. это не троллинга ради, мне действительно интересна альтернатива.

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

а, ну да. во всём важна умеренность и рациональное зерно. 100% - абстракций ради абстракций не нужно. но вот по моему опыту, "лёгкость" работы с проектом который пытается в солид и который не пытается где-то 8 к 2 соответственно

за сколько лет работы ни разу не приходилось объясняться терминами SOLID с непрогоаммистами. зачем вы вообще кому-то не коллеге рассказываете что-то подобное?

Начальство разное бывает.

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

Да половина FOSS мира такая. GCC. Linux (как минимум ядро). FreeBSD, NetBSD, OpenBSD (полный комплект). Причём я не говорю о специфически ассемблерных компонентах или тому подобном - а исключительно о центральной логике. Или вот загляните в .NET runtime. Код gc это полтора мегабайта плетёной логики только в одном центральном файле. И работает же, неплохо работает. У меня есть примеры и пожёстче, но я отложу их для подходящего случая.

На самом деле и в них полно случаев принципов из SOLID. Single responsibility - контролирует, чтобы не было посторонней функциональности там, где она не нужна и мешает гибкости. Liskov substitution principle - например, работа с файлами в ядре через вызов функций в softc-структурах - полный аналог полиморфизма на виртуальных функциях с выполнением контракта для каждого вызова (грубо говоря, read() не выполняет запись). Аналогично для VFS и массы других уровней. Open/close выражается в требованиях стабильности API ядра и системных библиотек. И так далее. Но главное то, что они не циклятся на этих принципах! Где они нужны - они соблюдаются. Где нет - их игнорируют. Если они мешают эффективности - принципы идут нафиг. Базовые требования там совсем другие.

Начальство разное бывает.

естественно, но про солид не специалисту? что-то за гранью))

в приведенной выборке уклон на системщину (gc в том числе). может поэтому у вас складывается такое впечатление про солид?

но про солид не специалисту? что-то за гранью))

Полу-специалисту, если точно сказать. Который выучил слова по книгам, но сам в лучшем случае ушёл из программирования N лет назад. Или, может, был только QA.

в приведенной выборке уклон на системщину

Вы начинаете понимать. См. опять "Пять миров" Спольски. Он там явно говорит, что все эти суперподходы годятся только для одного домена - из пяти рассмотренных им - который "внутреннее ПО" (точный термин из погибшего перевода на русский).

Но на самом деле ситуация ещё хуже. Даже в том, что выглядит как "образцовое" "внутреннее ПО", эти подходы годятся только для части из задач - хоть и занимающей >50% всей работы.

Полу-специалисту, если точно сказать. Который выучил слова по книгам....

тем не менее - это не аргумент против солид

Вы начинаете понимать

полегче на поворотах

См. опять "Пять миров" Спольски. 

его категоризация не связана с солид, выводы из этого так же. плюс он застрял в мышлении где-то в девяностых

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

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

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

тем не менее - это не аргумент против солид

Вполне себе аргумент. Если бы SOLID был одной из множества идеологий, далеко не на ключевой позиции, возражений бы не было - но тогда, скорее всего, он был бы разобран по компонентам. Например, 'S' превращалось бы в несколько подходов, таких, как Information Expert и Low Coupling из GRASP. А I и D вообще были бы привязаны только к конкретной разновидности ООП.

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

полегче на поворотах

Я говорю исключительно о том, что вы начинали (кажется...) понимать мою мысль. Если вам кажется, что в этой дискуссии было что-то некорректное с моей стороны, то вам следует пересмотреть своё восприятие.

его категоризация не связана с солид

И не должна.

плюс он застрял в мышлении где-то в девяностых

Да, у него не учтено, как эти подходы превращаются в современном мире с засильем веба. Но они тривиально мапятся на современную обстановку.

системное программирование и эмббэд - с солид сложно в виду специфики железа.

Вполне возможно. Но не только с ними "сложно" "ввиду специфики". Вы почему-то представляете тут построение "солидоцентричного" мышления, в котором всё, где SOLID не подходит, это какая-то особая периферия индустрии, я правильно понял? Тогда какие у вас основания считать соотношение "основы" и "периферии" такими, кроме веры в "дядю Боба"?

да особая каста.

И таки "особая", да. Ну, попробуйте это доказать.

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

И заодно доказать причинно-следственную связь в этом утверждении.

по теме статьи.

Так вы ж уже раньше обобщили до всей индустрии.

Вполне себе аргумент

нет. это ваши проблемы взаимоотношений с некоторыми людьми

И не должна

должна, раз приводится как аргумент

следует пересмотреть своё восприятие.

тон смените. начинаете хамить.

Так вы ж уже раньше обобщили до всей индустрии

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

удачи

тон смените. начинаете хамить.

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

удачи

Взаимно:)

С SOLID проблема в том, что это попытка формализации и представление идеологии Дяди Боба (да, я его последователь) в виде правил. Это выхолащивает его идеи. Очень часто читатели и те, кто знакомится с SOLID по википедии, неправильно понимают его (особенно SRP, так что даже Дядя Боб ругался и выпускал специально ролик, где объяснял смысл).

Да, я тоже после поверхностного ознакомления с SOLID думал, что это какая-то ахинея. После прочтения "желтой книги" все стало на свои места и отторжение исчезло.

Чистый код - это идеология и руководство к действию. Там нет и не может никаких конкретных правил, которые можно перевести в правила проверки кода. Программирование - это искусство.

Нет там никаких противоречий, тумана и симулякров.

upd. Если есть у вас навскидку ссылки на критику "Чистого кода" и отдельно SOLID, буду очень благодарен.

После прочтения "желтой книги" все стало на свои места и отторжение исчезло.

Это значит - здравый смысл, базовая теория и опыт собрались у вас в некоторую стройную концепцию. Верю. У нормальных специалистов так и должно происходить.

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

Нет там никаких противоречий, тумана и симулякров.

Они есть именно в том, что думающему не нужен конкретный композит по имени SOLID.

Если есть у вас навскидку ссылки на критику "Чистого кода" и отдельно SOLID, буду очень благодарен.

Таких не видел. Но можно разобрать те, что в топе поиска, по аспектам.

Именно! Кто-то, прочитав Дядю Боба, решил формализовать и намутил SOLID. Я не верю, что это сделал именно Дядя Боб. Этим самым, он охолостил и умертвил идеи Дяди.

Upd. Да, Майкл Фэзерс.

Да, Майкл Фэзерс.

В статье Мартина от 2000 перечисляются 4 принципа из 5. Там нет только 'S'. Приклеить его к остальным - я не думаю, что Фезерс тут сделал что-то существенное.

А статья показательная, безусловно. Потому что там "Principles of object-oriented design" как раз и показывают очень специфическое понимание, что есть в его случае object-oriented, и на чём именно он сделал основной акцент.

Но важно даже не это, а то, что сам Мартин принял это SOLID и дальше сам стал его активно распространять. И никакой Фезерс его тут не оттеснял, не шантажировал, и всё такое - это было сознательное добровольное решение.

Поэтому я категорически не соглашаюсь с обвинением кого-то ещё. Нет, "дядя Боб" сделал это сам и ответственность персонально на нём.

Во-первых, мне вообще не нравится слово "антипатерн". Потому что все эти приемы проектирования имеют и достоинства, и недостатки, а потому - свою область применения. А ярлык "антипатерн" отвергает прием проектирования вообще и всегда, в духе высказывания "четыре хорошо - две плохо".

Конкретно по вашему примеру: если формат сообщения специфичен для транспорта, то вытаскивать этот специфичный формат наружу плохо: через Message наружу вылазит sequential coupling, и при попытке модификации кода оно себя проявит: например, если mapToEventMessage тоже будет реализован через аггрегацию, то в дальнейшем при замене kafkaTemplate на другой транспорт влегкую можно забыть поменять реализацию создания сообщений. Наследование (ещё один якобы "антипаттерн") может несколько сгладить проблему - поскольку производный класс выступит абстрактной фабрикой, создающей согласованные друг с другом реализации аггрегируемых компонентов, но оно указанную coupling не устраняет.

С другой стороны, реализация через sendEvent не столь страшна. Наприме, она тоже вполне может абстрагиоваться от обработки ошибок на нижележащих уровнях - особенно если все эти ошибки будут обернуты в исключения одного и того же типа : sendEvent получит сведения, что попытка послать сообщение провалилась (а registerClient все равно необходимо это знать и где-то обрабатывать, так почему бы не в sendEvent), выполнит необходимую очистку (если она необходима) и передаст исключение наверх, не вдаваясь в его детали.

Если там, наверху, эти детали кому-то нужны (например, статистику работоспособности транспорта сообщений собрать), то их можно передать, к примеру, через вложенное исключение.

А вот если формат сообщения универсален для разных транспортов, то тут эта самая "сороконожка" действительно не нужна и даже вредна.

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

Касательно ваших воображаемых ситуаций.

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

Формат сообщения в примере не специфичен для транспорта.

поскольку производный класс выступит абстрактной фабрикой

Попытка решить проблему дизайна через сокрытие за абстракциями ничего, кроме избыточной сложности, не приносит. Существует несколько известных мне прагматичных принципов, указывающих на необходимость введения абстракций — правило триангуляции и правило трёх конвертов. Оба утверждают, что в данном коде абстракции не нужны.

может несколько сгладить проблему

Подобным образом слой свежей шпатлёвки сглаживает неровности кузова машины.

при замене kafkaTemplate на другой транспорт влегкую можно забыть поменять реализацию создания сообщений

Утверждение указывает на тот факт, что в сервисе не предполагается наличие каких-либо тестов. Обратите, пожалуйста, внимание на раздел "Рекомендации" и роль тестов в решении проблем дизайна. Возможно, уделение тестам достаточного внимания укоренит мысль о том, что нельзя при разработке забыть поменять реализацию создания сообщений.

она тоже вполне может абстрагироваться от обработки ошибок на нижележащих уровнях

Абстрагирование действительно может скрыть не только детали обработки ошибок, но и ошибки дизайна. Чем больше абстракций, тем глубже кроличья нора. Использование подхода One pile позволит в эту нору не угодить.

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

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

Дык, я же вам на это и указывал. Но если это требует повторения - повторю: верная или неверная декомпозиция кода - это зависит от решаемой задачи, от контекста. И я показал вам, что в определенном контексте, который вполне подходит к предмету статьи, ваш подход хуже, а этот, якобы "антипатерн" - наоборот, лучше. То есть, ваш вывод имеет гораздо более узкую область применения, чем можно подумать, исходя из текста статьи. Но в этой области он верен, не спорю. Но статья эту область применимости не оговаривает, поэтому ваш вывод в этом, более широком, контексте неверен.

Формат сообщения в примере не специфичен для транспорта.

Если бы на это было указано в статье, моих возражений бы не было. Но было ли это указано?

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

Избыточна ли эта сложность или нет - это зависит от конкретной задачи. Если выбрать неверный уровень сложности, то можем получить, с одной сторны, "FizzBuzz Enterprise edition", с другой - матерое, очень упорно и нередко успешно сопротивляющееся любой модификации, legacy с прибитыми гвоздями друг к другу частями.

Выбор нужного уровня абстракции - это вопрос искусства автора программы, причем - именно искусства: хорошего работающего всегда способа ("серебяной пули") нет. Ну, а вообще без абстракций программирование в современном виде просто невозожно, поскольку переменная - это уже абстракция.

Впрочем, к термину "абстрактная фабрика" все эти разговоры про абстракции имеют слабое отношение: это - устоявшееся за три десятка лет, прошедших с выхода известной книги от Четверки(GoF) название конкретного приема программирования.

Утверждение указывает на тот факт, что в сервисе не предполагается наличие каких-либо тестов. Обратите, пожалуйста, внимание на раздел "Рекомендации" и роль тестов в решении проблем дизайна. Возможно, уделение тестам достаточного внимания укоренит мысль о том, что нельзя при разработке забыть поменять реализацию создания сообщений.

Ваше возражение похоже на возражения поклонников языков типа JavaScript или Python против статической типизации: мол, зачем она нужна, если все можно проверить тестами. Такие возражения игнорируют то, что ошибку лучше не допускать, а допустив - обнаружить как можно быстрее: при компиляции или даже раньше. Тесты - уже следующая линия обороны против ошибок, выявление и исправление ошибок тестами обходится дороже (но дешевле, конечно, чем исправлять ошибки на бою).

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

Это - с одной стороны. А с другой, выбранную заранее архитектуру сложно поменять в процессе модификации приложения - а модификация сколь-нибудь успешно работающего приложения по жизни потребуется обязателно. Вот и приходится балансировать, выбирая без достаточной информации. И чтобы это делать успешно, нужен пресловутый опыт. А ещё - чутьё, которое обычно на основании опыта и появляется.

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

Дык, кто бы спорил? Только вот проблема - в том, чтобы понять какой код - излишний, а архитектурные решения - ненужные. И решать ее можно только творчески, для каждого конкретного случая отдельно. А для выбора решения - привыкнуть пользоваться всем богатсвом приемов, а не отвергать их бездумно, потому что они, якобы, "антипаттерн".

Собственно, в этом и основная мысль моего комментария: не надо бездумно записывать в "антипаттерны" никакие приемы программирования. Ибо "и терпентин на что-нибудь полезен!"(с)

повторю: верная или неверная декомпозиция кода - это зависит от решаемой задачи, от контекста.

Это не так, я вполне четко указал, почему декомпозиция была не верной и чем лучше чистая функция. Чистая функция дешевле в поддержке чем нечистая, это факт.

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

Тут вы глубоко заблуждаетесь, пространные рассуждения о несуществующих проблемах не являются аргументацией. При этом вы не привели контр аргументов к моим доводам.

Если бы на это было указано в статье, моих возражений бы не было. Но было ли это указано?

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

Избыточна ли эта сложность или нет - это зависит от конкретной задачи. 

В контексте примера статьи предложенные вами решения это избыточная сложность, обоснованная спекулятивным представлением о будущем.

Выбор нужного уровня абстракции - это вопрос искусства автора программы

Основная цель архитектуры приложения это снижение издержек на разработку и сопровождение. Все разговоры об искустве в контексте темы - это продукт богатого воображения и не прагматичного подхода к разработке.

хорошего работающего всегда способа ("серебяной пули") нет. 

Есть, принцип бритвы Оккама - "Не следует множить сущее без необходимости", влияние этой идеи прослеживается в огромном количестве эмпирических принципов.

Такие возражения игнорируют то, что ошибку лучше не допускать

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

Тесты - уже следующая линия обороны против ошибок, выявление и исправление ошибок тестами обходится дороже

Это не так. Тесты это дешевый способ проверки того, что программа выполняет требуемый контракт.

Только вот проблема - в том, чтобы понять какой код - излишний, а архитектурные решения - ненужные.

Такой проблемы не существует, код который не несет пользы - лишний. Например предложенные вами абстракции.

И решать ее можно только творчески, для каждого конкретного случая отдельно.

Это только при недостатке знания, когда "Голь хитра, голь мудрена, голь на выдумки горазда". Существует целый ворох принципов, которые говорят - не пишите лишний код, пишите простой код, не нагораживайте заранее ничего.

В целом было бы круто, если бы вы подтверждали свою позицию хоть какими-то аргументами. К примеру утверждение "выявление и исправление ошибок тестами обходится дороже" требует обоснований.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации