Моно репа или мульти репа никак ничего не гарантирует, но и не мешает (при правильно поставленном процессе разработки).
Отлично мешает. Я жил с моно репо и сейчас мульти — и я счастлив, что я ни от кого не завишу в своем маленьком мирке микросервиса. А не так что хочешь ЖДК11 но фиг тебе, потому пока все не переедут не будет ЖДК 11, а для этого надо синхронизировать все команды. Что практически нереально.
Примеры гигантских монореп в MS и в Google, где далеко не самые глупые разработчики, — это показывает.
Я работал как то в проекте по интеграции MS Teams в наш продукт. Они может и умные, но то что делается за пару часов, с ними тратились недели.
Я про то, что выполнив изолированное тестирование вы только получаете отмазку, что «у меня всё работает».
Так что мешает в моке эмулировать ошибки данных или таймауты? Потому при интеграционном тестировани вам развернуть все микросервисы и для конкретного use case сделать задержу а для других нет будет стоит больших усилий.
и отлично протестированная изолированными тестами система не может работать.
Она не отлично протестирована, тк что моки что интеграционные тесты могут быть разными. И когда я пишу микросервис я изначально закладываюсь на ошибки вызываемого мной другого сервиса и проверяю поведение при таких ошибках. Для этого мне надо моно репо и поднятие всех сервисов.
Go же язык со строгой типизацией.
расскажите это когда куда не плюнь interface{} а дальше кастуй :)))
IDE показывает именно те методы, что имеют отношение к конкретной структуре.
В Джаве у меня есть класс А у него есть публичные и приватные поля и методы. Когда я нахожусь в другом классе Б даже если они в одном пакадже то я все равно не увижу приватных полей и методов в авто комплите. В Го вы их не увидете только если класс Б в другом пакадже, а если пакадж тот-же то вся структура открыта для вас.
Так вот отладка именно внешней части и занимает львиную часть времени. По причине того, что публичные контракты не всегда исчерпывающе описаны.
Если это публичные контракты внутри своей организации, то это значит так разработка посстроена. Если же внешние, то как это связано с моно репо против мульти репо?
Но почему то интеграционные тесты делают «на отвяжись, у меня контракт соблюден, моком-имитатором все проверил, а дальше хоть трава не рости»
Если вы про то, что разработчик сервиса А не тестирует сервис Б, а берет делает моки для Б и тестирует А. То не зная всех деталей можно сказать что он прав. Тк это ответсвеность сервиса Б тестировать свой публичный контракт и работоспосоюность. И сервис А должен лишь тестировать свое поведение если что то пошло не так.
Конкретно наш текущий проект отдаёт и принимает данные по чужим (внешним) API. И это не какие-то вторичные API, а именно то, за ради чего весь проект создавался.
а как это поможет когда у вас монорепо или нет? Если у вас проблема с одинм конкретным сервисом.
У вас один сервис принимает данные и дальше должен их конвертить во внутренний правильный формат и уже ими должны пользоваться остальные внутренние микросервисы. И тестировать вам надо только вот этот наружу смотрящий севрис. Это как я вижу.
У нас сотни микросервисов с 1-10К RPS на каждом. И мне не разу не сломали внешний (который на самом деле внутренний но для других микросервисов он внешний) контракт так же как и я другим. СЕрвисы которыми я заведую ходят в различные внешние системы, например Zoom и другим нашим сервисам абсолютно все равно что я там с тем Зумом делаю. Главное чтобы я им отдавал нормальные данные которые соответсвуют опять же публичному контракту.
Как уже упомянули в соседнем комменте, package private по идее должно быть достаточно, чтобы скрыть реализацию.
Нет, сокрытие на уровне пакаджа что не тоже самое что на уровне класса. И много вы видели в Го проектов в которых каждая страктура в своем классе? Я вот не видел.
в которых невозможно вообще ничего расширить как раз из-за паранойи разработчика
Если вы хотите во внутрь библиотеки то fork и вперед. Вы уже своим желанием показываете что текущаа имплементация вам не подходит и вы готовы сломать совместимость, используя внутрености.
Как только вы захотите делать полное интеграционное тестирование всех микросервисов на регулярной основе
Я не знаю зачем мне это надо. Меня не интересуют внутрености остальных микросервисов так же как и их внутрености моего. Главное соблюдение публичного контракта. И больше нет проблем. А когда надо менять контракт то проще добавить новый ендпоинт и создать ишью на другие команды по миграции. И жить себе дальше а не пытаться заставить в монорепе чтобы остальные команды все бросили и пошли в вашей ветке фиксить использование вашего ендпоинта.
Те вроде как у вас микросервисы а на самом деле респределенный монолит, в котором сменить ждк 8 на ждк 11 нереально тк надо чтобы вся кодовая база поменялась.
Что касается спора, учитывая мой бэкграцнд, я бы скорее сам предпочел писать на джаве, а уж никак не на Го
И так на каждую структуру? Я не хочу чтобы были видны кишки и доступ к ним кого либо кроме этого класса/структуры.
В чем проблема в пределах одного пакета, когда вы еще можете охватить одним мысленным взглядом, вести себя с переменными корректно?
тем что за этим надо следить когда другой язык избавляет вас от этого. Даже банальный автокомплит IDE мне в джаве будет показывать публичные поля, методы а не всю партянку и дальше сиди разбирайся можно этим пользоваться или это что то внутреннее.
Ну кмк Го покрывает большинство кейсов приватными и публичными структурами и функциями. Да, наверное, не так полно, как это в Джаве.
В Джаве у меня самые ходовые это public и private. В Го у меня нет private а максимум package и это значит я не могу ограничить доступ к ней. А значит у вас уже утекает информация наружу. И вы не можете гарантировать, что использовать будут как надо ваш код, а не как кому голову взбредет.
Го не гарантирует вам обработку ошибок, это уже мы обсуждали в другой статье. Так же Го не дает вам ни ООП ни функционального программирования ни какого другого подхода. В большом и сложном проекте у вас обязательно будут лезть со всех стороно interface{} и никакой гарантии на этапе компиляции вы не получите. А только в рантайме прилетят проблемы.
Я уже как то предлагал спор — вы пишите на Го а я на Джаве. А потом сравниваем затраченное время, производительность и архитектуру в целом. Почему не согласились :)))
Но, честно говоря, я 6икогда не понимал всех этих огораживания, когда код библиотеки пишут так, что ты его не можешь расширить. С моей точки зрения это скорее минус.
Расширить и залезть в кишки это разные вещи.
Тут вопрос ее в монорепе, а в желании тестировать каждый коммит.
это именно монорепо — потому что у нас в компании сотни микросервисов и протестировать и собрать каждый из них дело быстрое. А когда у вас монорепо то вам на каждый чих надо на холодном агенте выкачивать весь репозиторий и все зависимости.
Это 100% так. Если в лоб императивно писать реактивщину, то да выходит ужасно. Поэтому надо изначально писать как поток данных, с разбиением по слоям и разным классам и тогда никаких проблем нет. Это как и Джава stream можно ужас наворотить, а можно сделать красивое понятное решение.
Абстракции могут утечь на любом языке, и на Джаве в частности.
Могут и будут разные вещи. Простой пример в Джаве вы сделали класс с приватным конструктором, private final полями и билдером и можете быть уверены что никто по другому его не будет использовать. В Го вы это просто не сможете реализовать (одна структура в пакете не рассматриваем тк это вообще не жизнеспособный вариант).
Ну это конкретная проблема, которую я вижу ежедневно, когда 200+ разработчиков коммитят в мастер и запускают свои билды на 300+ ci-агентах
Во-первых, мне очень жаль что вам приходится мучаться на моно репе :)
Во-вторых, откуда тогда взялась большая проблема холодных ci-agent'ов в таком сценарии.
Важно сделать так, чтобы когда система начнет расти, ее можно было легко смасштабировать
Я сам лично писал несколько проектов на RxJava, более сложно тестируемого кода я не видел
А что не так с этим кодом? По моему мнению разницы сопровождать и тестировать код который User getById(String id) vs Mono<User> getById(String id) разницы нет.
Я работаю не в Гугле (то есть я не Гугл) но у меня сейчас размеры всего такие, что сборка, регрессия, деплой и прочее занимают часы.
Значит у вас огромный проект и в Го у вас абстракции и структуры утекут и получится такая каша, что время компиляции будет цветочками :)
и меньшее время скачивания контейнеров на холодном CI-агенте
это какой кто граничный случай, что я бы не расматривал его. Только еще учтите что в Джаве вы взяли мавен и у вас все проекты практически одинаковые по layout и как собираются. Плюс плагинами вы можете много разного делать и это будет работать одинаково как в Дженкинсе так и у разработчиков под разными ОС. А в Го вы будете писать свой велосипед потому что там либо go build но такое катит для элементарных проектов либо портянки на make который под линуксом все ок, а под Виндовс начинаются пляски либо берете Bazel и мудохаетесь с ним. А в это время джава версия уже захватывает рынки.
нет ни try...catch и за меня все делает Flux/Mono, которые вполне себе Монады :)
Когда счёт пойдет на сотни и тысячи хостов, это все зачтется.
You Are Not Google
Обычно на каждом хосте бегают десятки микросервисов, а значит и экономия будет на слоях.
А если случилось так что у нас на каждом хосте по одному микросервису то разницы в цене не будет. Тк в том же амазоне вы EBS покупаете от Гб в месяц — в Орегоне 0,10 USD за ГБ-месяц выделенного хранилища.
Java уже будет в продакшене. Размер докера контейнера тоже по большому не играет роли, тк в Го у вас будет допустим 20Мб, а в Джава 200Мб но вы можете разбить на слои и изменяемый слой с вашим кодом будет весить пару Кб.
Для себя я выробатал стратегию — нет жестких ограничений по памяти берем Джава, а там где есть берем Раст. Го без вливания Гугла давно бы умер тк как язык он вообще не интересен.
В который раз не понимаю зачем на Го пытаться такое писать, потому что выходит или детская поделка или надо так обмазаться кодом, чтобы были и нормальные абстракции и они никуда не текли и ошибки все обрабатывались нормально, что в результате потратите времени когда другие уже закончат три таких проекта.
Полнстью согласен. когда РЕСТ ендпоинт вырождается в
@GetMapping
public OperationDto getOperationById(@PathVariable("id") Long id) {
return operationService.getById(id);
}
то потом оказывается, что это больно когда для Веб клиента надо отдать одно, а для мобильного чуть другое.
Сервис отдает свою структуру а уже презентационый слой, который в данном случае ендпоинт, сам решает как ему отображать данные или ошибки.
С Кваркусом и нативным образом у меня засада, что локальная машина под МакОС, а образ надо делать для Линукса. И значит надо собирать проект в докере, а докер у меня висит с ограниченными ресурсами, чтобы не выжирал всю память и цпу. В результате все собирается очень долго :(
а какая разница на размер контейнера?
Если вы правильно сделаете слои то меняться будет слой только с вашим кодом. И значит хосты будут вытягивать только его, а не весь образ.
Зачем мне переписывать логику сервиса и его АПИ если ДТО будет приходить такой же.
Везде по коду там где не надо использование этих новых полей ничего меняться не будет, так же не будет меняться АПИ.
А добавление столбцов в живую систему всегда подразумевает что null это нормальное значение или делается миграция и к существующим данным в базе добавляется нужная информация.
Можете показать пример?
Отлично мешает. Я жил с моно репо и сейчас мульти — и я счастлив, что я ни от кого не завишу в своем маленьком мирке микросервиса. А не так что хочешь ЖДК11 но фиг тебе, потому пока все не переедут не будет ЖДК 11, а для этого надо синхронизировать все команды. Что практически нереально.
Я работал как то в проекте по интеграции MS Teams в наш продукт. Они может и умные, но то что делается за пару часов, с ними тратились недели.
Так что мешает в моке эмулировать ошибки данных или таймауты? Потому при интеграционном тестировани вам развернуть все микросервисы и для конкретного use case сделать задержу а для других нет будет стоит больших усилий.
Она не отлично протестирована, тк что моки что интеграционные тесты могут быть разными. И когда я пишу микросервис я изначально закладываюсь на ошибки вызываемого мной другого сервиса и проверяю поведение при таких ошибках. Для этого мне надо моно репо и поднятие всех сервисов.
В Джаве у меня есть класс А у него есть публичные и приватные поля и методы. Когда я нахожусь в другом классе Б даже если они в одном пакадже то я все равно не увижу приватных полей и методов в авто комплите. В Го вы их не увидете только если класс Б в другом пакадже, а если пакадж тот-же то вся структура открыта для вас.
Если это публичные контракты внутри своей организации, то это значит так разработка посстроена. Если же внешние, то как это связано с моно репо против мульти репо?
Если вы про то, что разработчик сервиса А не тестирует сервис Б, а берет делает моки для Б и тестирует А. То не зная всех деталей можно сказать что он прав. Тк это ответсвеность сервиса Б тестировать свой публичный контракт и работоспосоюность. И сервис А должен лишь тестировать свое поведение если что то пошло не так.
а как это поможет когда у вас монорепо или нет? Если у вас проблема с одинм конкретным сервисом.
У вас один сервис принимает данные и дальше должен их конвертить во внутренний правильный формат и уже ими должны пользоваться остальные внутренние микросервисы. И тестировать вам надо только вот этот наружу смотрящий севрис. Это как я вижу.
У нас сотни микросервисов с 1-10К RPS на каждом. И мне не разу не сломали внешний (который на самом деле внутренний но для других микросервисов он внешний) контракт так же как и я другим. СЕрвисы которыми я заведую ходят в различные внешние системы, например Zoom и другим нашим сервисам абсолютно все равно что я там с тем Зумом делаю. Главное чтобы я им отдавал нормальные данные которые соответсвуют опять же публичному контракту.
Нет, сокрытие на уровне пакаджа что не тоже самое что на уровне класса. И много вы видели в Го проектов в которых каждая страктура в своем классе? Я вот не видел.
Если вы хотите во внутрь библиотеки то
forkи вперед. Вы уже своим желанием показываете что текущаа имплементация вам не подходит и вы готовы сломать совместимость, используя внутрености.Я не знаю зачем мне это надо. Меня не интересуют внутрености остальных микросервисов так же как и их внутрености моего. Главное соблюдение публичного контракта. И больше нет проблем. А когда надо менять контракт то проще добавить новый ендпоинт и создать ишью на другие команды по миграции. И жить себе дальше а не пытаться заставить в монорепе чтобы остальные команды все бросили и пошли в вашей ветке фиксить использование вашего ендпоинта.
Те вроде как у вас микросервисы а на самом деле респределенный монолит, в котором сменить ждк 8 на ждк 11 нереально тк надо чтобы вся кодовая база поменялась.
И вот чего мы тогда тут спорим :)))))
Взять рефлексию и заморочится это немного не тоже самое что выбрать поле из списка доступных в структуре в ИДЕ и пойти работать с ним.
Так же никто не отменял SecurityManager если стоит проблема очень остро.
И если не в курсе то джава 9+ позволит сделать такие ограничения по рефлексии на уровне модулей.
Так что не хахаха
И так на каждую структуру? Я не хочу чтобы были видны кишки и доступ к ним кого либо кроме этого класса/структуры.
тем что за этим надо следить когда другой язык избавляет вас от этого. Даже банальный автокомплит IDE мне в джаве будет показывать публичные поля, методы а не всю партянку и дальше сиди разбирайся можно этим пользоваться или это что то внутреннее.
В Джаве у меня самые ходовые это
publicиprivate. В Го у меня нетprivateа максимумpackageи это значит я не могу ограничить доступ к ней. А значит у вас уже утекает информация наружу. И вы не можете гарантировать, что использовать будут как надо ваш код, а не как кому голову взбредет.Го не гарантирует вам обработку ошибок, это уже мы обсуждали в другой статье. Так же Го не дает вам ни ООП ни функционального программирования ни какого другого подхода. В большом и сложном проекте у вас обязательно будут лезть со всех стороно
interface{}и никакой гарантии на этапе компиляции вы не получите. А только в рантайме прилетят проблемы.С производительности в Го тоже не все хорошо. И с памятью есть проблемы
Я уже как то предлагал спор — вы пишите на Го а я на Джаве. А потом сравниваем затраченное время, производительность и архитектуру в целом. Почему не согласились :)))
Расширить и залезть в кишки это разные вещи.
это именно монорепо — потому что у нас в компании сотни микросервисов и протестировать и собрать каждый из них дело быстрое. А когда у вас монорепо то вам на каждый чих надо на холодном агенте выкачивать весь репозиторий и все зависимости.
Это 100% так. Если в лоб императивно писать реактивщину, то да выходит ужасно. Поэтому надо изначально писать как поток данных, с разбиением по слоям и разным классам и тогда никаких проблем нет. Это как и Джава stream можно ужас наворотить, а можно сделать красивое понятное решение.
Могут и будут разные вещи. Простой пример в Джаве вы сделали класс с приватным конструктором,
private finalполями и билдером и можете быть уверены что никто по другому его не будет использовать. В Го вы это просто не сможете реализовать (одна структура в пакете не рассматриваем тк это вообще не жизнеспособный вариант).Во-первых, мне очень жаль что вам приходится мучаться на моно репе :)
Во-вторых, откуда тогда взялась большая проблема холодных ci-agent'ов в таком сценарии.
не понимаю как это связано с Го или Джавой
А что не так с этим кодом? По моему мнению разницы сопровождать и тестировать код который
User getById(String id)vsMono<User> getById(String id)разницы нет.Значит у вас огромный проект и в Го у вас абстракции и структуры утекут и получится такая каша, что время компиляции будет цветочками :)
это какой кто граничный случай, что я бы не расматривал его. Только еще учтите что в Джаве вы взяли мавен и у вас все проекты практически одинаковые по layout и как собираются. Плюс плагинами вы можете много разного делать и это будет работать одинаково как в Дженкинсе так и у разработчиков под разными ОС. А в Го вы будете писать свой велосипед потому что там либо
go buildно такое катит для элементарных проектов либо портянки наmakeкоторый под линуксом все ок, а под Виндовс начинаются пляски либо берете Bazel и мудохаетесь с ним. А в это время джава версия уже захватывает рынки.в том то и дело, что Джава огромная и вы можете писать на ней в любом стиле.
Вот кусок с реального проекта
нет ни
try...catchи за меня все делаетFlux/Mono, которые вполне себе Монады :)Пока вы будете на Го описывать
Java уже будет в продакшене. Размер докера контейнера тоже по большому не играет роли, тк в Го у вас будет допустим 20Мб, а в Джава 200Мб но вы можете разбить на слои и изменяемый слой с вашим кодом будет весить пару Кб.
Для себя я выробатал стратегию — нет жестких ограничений по памяти берем Джава, а там где есть берем Раст. Го без вливания Гугла давно бы умер тк как язык он вообще не интересен.
Redis Streams нормально заходят в этом случае и нет Pub/Sub проблем.
Все ваши доменные структуры открыты и публичны
те делай кто хочешь что хочешь.
Хочешь создавай структуру с отрицательной суммой и датой в будущем.
Стандартная беда Го, что хотим то и пихаем в лист. Никакой безопастности.
Те если не смогли закомитить транзакцию, то смерть всему приложению???
В который раз не понимаю зачем на Го пытаться такое писать, потому что выходит или детская поделка или надо так обмазаться кодом, чтобы были и нормальные абстракции и они никуда не текли и ошибки все обрабатывались нормально, что в результате потратите времени когда другие уже закончат три таких проекта.
Полнстью согласен. когда РЕСТ ендпоинт вырождается в
то потом оказывается, что это больно когда для Веб клиента надо отдать одно, а для мобильного чуть другое.
Сервис отдает свою структуру а уже презентационый слой, который в данном случае ендпоинт, сам решает как ему отображать данные или ошибки.
С Кваркусом и нативным образом у меня засада, что локальная машина под МакОС, а образ надо делать для Линукса. И значит надо собирать проект в докере, а докер у меня висит с ограниченными ресурсами, чтобы не выжирал всю память и цпу. В результате все собирается очень долго :(
а какая разница на размер контейнера?
Если вы правильно сделаете слои то меняться будет слой только с вашим кодом. И значит хосты будут вытягивать только его, а не весь образ.
Зачем мне переписывать логику сервиса и его АПИ если ДТО будет приходить такой же.
Везде по коду там где не надо использование этих новых полей ничего меняться не будет, так же не будет меняться АПИ.
А добавление столбцов в живую систему всегда подразумевает что null это нормальное значение или делается миграция и к существующим данным в базе добавляется нужная информация.