А есть вариант как "разрулить" 2 типа логов и отправлять их в разные места? Например, мы пишем в stdout контейнера json-данные для OpenTelemetry, а в stderr json-данные для Loki.
У меня нет цели вас переубедить, со временем, понимание само придет. Но размещая всю логику в контроллере, вы заставляете его знать больше чем требует его зона ответственности.
Хм, для меня структурирование кода только уменьшает нагрузку при чтении нового кода. А если эта структура идет из проекта в проект, из модуля в модуль, то всё упрощается в разы. Согласен, не все готовы работать по определенным стандартам - это разрыв шаблона, это ограничение творческой жилки и тп. Я сам через это проходил, но опыт на разных проектах, чтение умных статей и просмотр выступлений помогли сформировать понимание, что стандартизация - это хорошо.
Оверинжиниринг будет ярко выражен на маленьких и простых проектах. В остальных случаях этот подход будет оправдан. Я писал в статье:Нет «серебряной пули», есть только путь в попытке найти баланс между трудозатратами, качеством и скоростью. И в каждому случае - он свой. И там же привел пару правил, которые для себя выработал для определения сложности.
Когда-то моя команда создавала несколько микросервисов, и там мы точно не задумывались над структурой папок. Там на один сервис было не более 20 файлов. Но проекту это не помогло, его закрыли. В сроки и бюджет не уложились, и скорость разработки тут была совершенно не причем. Часто заказчик хочет всё и вчера, но если подойти с умом, то сначала надо сделать MVP, который запустить на рынок и начать зарабатывать, и параллельно с этим допиливать новый функционал. И это всё можно делать с первых строк кода хорошо. Естественно не надо сразу проектировать коня в вакууме, делаем как умеем и только то что надо сейчас + готовим точки для расширения на будущее.
Хелсчек я привел, как пример, своей логики рассуждения. Если у меня сервис не планирует развиваться, например, учет прохода пациентов в клинику, то можно его сделать быстро и по простому. НО если выбран определенный подход, то он должен быть везде по всему коду и к этим правилам должны быть тесты. В противном случае будет хаос и через год-два, даже автор кода будет с трудом там разбираться.
Даже обновление мажорной версии фреймворка выливается в "смену", настолько сильные бывают изменения. И это было больно, тк изначально не захотели делать правильно, а делали побыстрее.
И вот если у тебя сегодня приложение работает на симфони, а завтра ты хочешь переехать на ларавель, то тебе надо на ларавели собрать новое приложение и поставить туда твой модуль.
Это и есть смена легкая фреймворка, достаточно только поправить связывающий слой. Бизнес логика не будет меняться.
Приложение - это средство для достижения цели, фреймворк - это инструмент. А бизнес логика - это самое ценное, то на чем компания зарабатывает деньги.
Бизнесу важно не с каким VIN будет перевозка песка, а сколько песка можно будет перевезти. Бизнесу все равно на ваше шасси, одно это транспортное средство или разные. Бизнесу ОЧЕНЬ важно, чтобы самосвал легко чинился и легко модернизировался под новые перевозки.
Мне кажется, у вас не правильно расставлены зависимости.
Фреймворк, как шасси, как и квартира - это средство реализации ваших желаний. А кузов или диван - это ваши потребности, созданные под ваши нужды. Мы можете взять свой любимый, удобный и мягкий диван и с ним переехать в любое место, тк для него нужен просто интерфейс взаимодействия с полом - ножки. Даже если пол кривой - под ножку можно что-то подсунуть (адаптер). Дивану даже пол не нужен - его можно подвесить, те берем новый адаптер.
Структура проекта - это стратегическое решение, которое должно базироваться на анализе конкретных бизнес‑требований, доступных ресурсов и сроков выполнения проекта!
Я знаю, что есть компании, которые экономят на всем. Тут можно только пытаться объяснять чем это грозит, искать компромиссы и убеждать выделять больше ресурсов. Это как с зубами: если ты их не чистишь, то сколько не лечи, все равно, в конечном итоге будет удаление.
Подходы "Framework agnostic" и "Anti-Corruption Layer" помогают изолировать бизнес логику от внешних зависимостей. Если код написан правильно, те разделен на модули и слои, то вынести кусочек приложения в самостоятельную библиотеку не составит труда. В итоге приложение будет включать в себя множество ваших библиотек с бизнес логикой и через адаптеры связывать их с конкретным фреймворком.
Это прям идеал, к которому надо стремится, но очень дорогой и трудоемкий идеал.
Пример очень удачный :))) Да, фреймворк - это шасси. Бизнес ставит вам задачу сделать кузов. Вы смотрите на рынок выбираете самое популярное шасси, НО чтобы не завязываться на одного производителя делаете кузов не под конкретное шасси, а через адаптер. Через год приходят санкции и запчасти на шасси заканчиваются. Понимая, что бизнес может встать, вы покупаете другое шасси и делаете для него адаптер. И планово переносите кузов на новое шасси. Так что шасси можно менять :))
На практике понятие "framework agnostic" можно применить только к отдельным программным компонентам.
Фреймворк - это просто инструмент. Его можно заменить, тут больше вопрос целесообразности этих действий.
Замена шасси в самосвале не будет выглядеть невозможной, если самосвал спроектирован модульно. Например, вы делаете кабину и к ней есть набор адаптеров для разных вид шасси, у кузова тоже есть свои адаптеры для крепления и т.д.
«проверка доступности» — такая же деталь, которая, наверное, имеет значение только для балансировки трафика.
Не только для балансировки, не всегда пользователи сразу сигнализируют об ошибке. Часто просто уходят с негативом. И даже когда они придут и скажут про ошибку, всегда приятнее им ответить: "наша система мониторинга уже сообщила о проблеме, мы сейчас с ней разбираемся и скоро всё исправим."
насколько эта структура поменяется, например, при смене фреймворка с Laravel на Symfony? Придётся ли переписывать что-то, кроме «клея» между бизнес-логикой и фреймворком? И, наверное, самый важный вопрос: как такая структура защищает от «прикипания» к конкретному фреймворку?
Я пробовал применить это к Симфони, всё точно так же и некоторые моменты даже проще чем в Ларе. В целом, защищает от "прикипания", особенно если на все важные места создавать адаптеры и декораторы.
В идеальном мире frameworkagnostic надо было бы создать свой адаптер на Illuminate, в этом есть минус - это дополнительное время на разработку и тестирование. Но так же это и плюс - при смене фреймворка либо самого либо его версии надо будет исправить только адаптер. В общем, надо искать баланс и где-то идти на уступки всей этой чистой идеологии.
Не совсем так и не в протоколе дело, а в том, что один модуль стал меньше знать о другом модуле. Самое банальное, как создать класс. Это другая зона ответственности. Да, есть паттерны, которые помогают решить эту проблему: DI или Фабрика. Но опять же мы навязываем знание о потребителе поставщику данных.
Утрированно: уменьшая связанность, мы уменьшаем у поставщика данных знания, кто эти данные будет использовать.
А есть вариант как "разрулить" 2 типа логов и отправлять их в разные места? Например, мы пишем в stdout контейнера json-данные для OpenTelemetry, а в stderr json-данные для Loki.
Очень интересен ваш опыт.
Если не секрет: у вас сколько человек в команде разработки и какие приняты правила по организации кода?
У меня нет цели вас переубедить, со временем, понимание само придет. Но размещая всю логику в контроллере, вы заставляете его знать больше чем требует его зона ответственности.
Всё зависит от ваших знаний и умений.
Хм, для меня структурирование кода только уменьшает нагрузку при чтении нового кода. А если эта структура идет из проекта в проект, из модуля в модуль, то всё упрощается в разы.
Согласен, не все готовы работать по определенным стандартам - это разрыв шаблона, это ограничение творческой жилки и тп. Я сам через это проходил, но опыт на разных проектах, чтение умных статей и просмотр выступлений помогли сформировать понимание, что стандартизация - это хорошо.
Оверинжиниринг будет ярко выражен на маленьких и простых проектах. В остальных случаях этот подход будет оправдан. Я писал в статье:
Нет «серебряной пули», есть только путь в попытке найти баланс между трудозатратами, качеством и скоростью. И в каждому случае - он свой.
И там же привел пару правил, которые для себя выработал для определения сложности.Когда-то моя команда создавала несколько микросервисов, и там мы точно не задумывались над структурой папок. Там на один сервис было не более 20 файлов. Но проекту это не помогло, его закрыли. В сроки и бюджет не уложились, и скорость разработки тут была совершенно не причем.
Часто заказчик хочет всё и вчера, но если подойти с умом, то сначала надо сделать MVP, который запустить на рынок и начать зарабатывать, и параллельно с этим допиливать новый функционал. И это всё можно делать с первых строк кода хорошо.
Естественно не надо сразу проектировать коня в вакууме, делаем как умеем и только то что надо сейчас + готовим точки для расширения на будущее.
Хелсчек я привел, как пример, своей логики рассуждения. Если у меня сервис не планирует развиваться, например, учет прохода пациентов в клинику, то можно его сделать быстро и по простому.
НО если выбран определенный подход, то он должен быть везде по всему коду и к этим правилам должны быть тесты. В противном случае будет хаос и через год-два, даже автор кода будет с трудом там разбираться.
Даже обновление мажорной версии фреймворка выливается в "смену", настолько сильные бывают изменения.
И это было больно, тк изначально не захотели делать правильно, а делали побыстрее.
Это и есть смена легкая фреймворка, достаточно только поправить связывающий слой. Бизнес логика не будет меняться.
Приложение - это средство для достижения цели, фреймворк - это инструмент. А бизнес логика - это самое ценное, то на чем компания зарабатывает деньги.
Бизнесу важно не с каким VIN будет перевозка песка, а сколько песка можно будет перевезти.
Бизнесу все равно на ваше шасси, одно это транспортное средство или разные.
Бизнесу ОЧЕНЬ важно, чтобы самосвал легко чинился и легко модернизировался под новые перевозки.
Мне кажется, у вас не правильно расставлены зависимости.
Фреймворк, как шасси, как и квартира - это средство реализации ваших желаний.
А кузов или диван - это ваши потребности, созданные под ваши нужды. Мы можете взять свой любимый, удобный и мягкий диван и с ним переехать в любое место, тк для него нужен просто интерфейс взаимодействия с полом - ножки. Даже если пол кривой - под ножку можно что-то подсунуть (адаптер). Дивану даже пол не нужен - его можно подвесить, те берем новый адаптер.
Да, есть такой нюанс, я об этом писал в статье:
Я знаю, что есть компании, которые экономят на всем. Тут можно только пытаться объяснять чем это грозит, искать компромиссы и убеждать выделять больше ресурсов.
Это как с зубами: если ты их не чистишь, то сколько не лечи, все равно, в конечном итоге будет удаление.
Подходы "Framework agnostic" и "Anti-Corruption Layer" помогают изолировать бизнес логику от внешних зависимостей.
Если код написан правильно, те разделен на модули и слои, то вынести кусочек приложения в самостоятельную библиотеку не составит труда. В итоге приложение будет включать в себя множество ваших библиотек с бизнес логикой и через адаптеры связывать их с конкретным фреймворком.
Это прям идеал, к которому надо стремится, но очень дорогой и трудоемкий идеал.
Пример очень удачный :)))
Да, фреймворк - это шасси. Бизнес ставит вам задачу сделать кузов. Вы смотрите на рынок выбираете самое популярное шасси, НО чтобы не завязываться на одного производителя делаете кузов не под конкретное шасси, а через адаптер.
Через год приходят санкции и запчасти на шасси заканчиваются. Понимая, что бизнес может встать, вы покупаете другое шасси и делаете для него адаптер. И планово переносите кузов на новое шасси. Так что шасси можно менять :))
В статье давал ссылку на Framework Agnostic длиной в 12 лет, там целый проект так живет.
Фреймворк - это просто инструмент. Его можно заменить, тут больше вопрос целесообразности этих действий.
Замена шасси в самосвале не будет выглядеть невозможной, если самосвал спроектирован модульно. Например, вы делаете кабину и к ней есть набор адаптеров для разных вид шасси, у кузова тоже есть свои адаптеры для крепления и т.д.
Не только для балансировки, не всегда пользователи сразу сигнализируют об ошибке. Часто просто уходят с негативом.
И даже когда они придут и скажут про ошибку, всегда приятнее им ответить: "наша система мониторинга уже сообщила о проблеме, мы сейчас с ней разбираемся и скоро всё исправим."
Я пробовал применить это к Симфони, всё точно так же и некоторые моменты даже проще чем в Ларе.
В целом, защищает от "прикипания", особенно если на все важные места создавать адаптеры и декораторы.
В идеальном мире framework agnostic надо было бы создать свой адаптер на
Illuminate,
в этом есть минус - это дополнительное время на разработку и тестирование. Но так же это и плюс - при смене фреймворка либо самого либо его версии надо будет исправить только адаптер.В общем, надо искать баланс и где-то идти на уступки всей этой чистой идеологии.
Для паттерна Chain of Responsibility существуют частные случаи ("подпаттерны"), например: Chain, Pipeline, and Middleware.
Более детально можно прочитать в статье https://orangesoft.co/blog/chain-of-responsibility-design-pattern-in-php
За последний год-два очень сильно развился https://yandex.cloud/ru/services/tracker
Не совсем так и не в протоколе дело, а в том, что один модуль стал меньше знать о другом модуле.
Самое банальное, как создать класс. Это другая зона ответственности. Да, есть паттерны, которые помогают решить эту проблему: DI или Фабрика.
Но опять же мы навязываем знание о потребителе поставщику данных.
Утрированно: уменьшая связанность, мы уменьшаем у поставщика данных знания, кто эти данные будет использовать.
Не думали выложить свое решение в открытый доступ?
Например: