Pull to refresh
22
0

User

Send message

Стратегии тестирования выбираются в зависимости от сложности бизнес логики и выбранной архитектуры.

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

Пирамида тестирования, не говорит что важны только unit тесты, она лишь определяет количественное соотношение различных видов тестов.

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

Внутри команды, потому что story point особо ничего не показывают. Если их оценивать по "сложности" задачи, то эта сложность меняется в процессе, когда приходит понимание бизнеса + есть уже наработки по кодовой базе. И получается их надо переоценивать, а тогда теряется смысл всех графиков на их основе.

По поводу waterfall, есть процессы сбора требований, составления документации и согласования этого с заказчиком, плюсом он получает сроки и смету, а команда железный roadmap, в котором можно запланировать этапы интеграции разных частей разрабатываемого приложения. Так же у команды появляется "вижн" общая цель и мотивация. Обычно на сбор требований и планирование я выделю 1 месяц (2 месяца если еще и команду надо подобрать), а MVP в моем понимании это проект 6 месяцев максимум.

В последних 4 командах, мы быстро отходили от story point-ов в пользу оценки по дням, сейчас и вовсе отказывались от оценки задач и перешли на trunk based development + kanban. На этапе MVP проекта я стараюсь сделать gitflow + waterfall если это возможно, а после выхода релиза, на этапе развития и поддержке проекта tbd + kanban + value stream mapping правда моим приоритетом всегда является скорость доставки "ценности" на прод, но далеко не все считают это важным.

Я пишу код больше 20 лет, разрабатываю сейчас cloud application на Go, поклонник unix way и не могу придумать зачем мне, как тех лиду, нужен rust на проектах.

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

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

На момент написания комментария на хабр карьере 5 вакансий rust разработчика и 197 вакансий на go разработчика.

Немного про async IO

node.js и Go из коробки поддерживают асинхронный ввод вывод (epoll, IOCP) надеюсь скоро в Go включат поддержку io_uring. Причем сам разработчик об этом и не знает, все происходит нативно. В rust же нужно использовать стороннюю библиотеку tokio.

Go из коробки имеет "горутины", которые автоматически масштабируются по количеству доступных процессоров. Если кто-то здесь изучал "параллельное программирование" тому известно что такое "переключение контекста" на уровне ОС и сколько это стоит. В rust насколько я понял используются системные потоки, со всеми вытекающими, а асинхронность Future однопоточная? Ну и немного цитаты из документации "Migrating from threads to async or vice versa typically requires major refactoring work"

Немного про shift-left-security

Мы в "компаниях" хотим безопасное по, для этого нам нужен SAST, DAST, SCA. SCA для go это govulncheck от самих создателей языка, SAST golangci-lint причем многие утилиты от самих создателей языка. Есть ли в rust подобная экосистема?

Закон Парето гласит, что во многих случаях 20% усилий дают 80% результата и я не вижу, где я могу применить rust в своей работе, что бы это было оправдано чем-то кроме "а давайте всё перепишем на rust". Надеюсь вы сможете меня переубедить :)

Я как раз и говорю о том, что группировать настройки по типам окружения в коде плохая затея. Потому что количество окружений может расти независимо от разработчика, например latest, release, qa, stress-test, dima-local, slava-docker-qa... Передавайте настойки логгера так же через env, а файл config.yaml, можно использовать как default values, если настроек очень много. В оркестраторах типа k8s, обычно default values, опрсаывется в helm chart.

Честно, внимательно прочитал не всё, остановился на константах env, local, prod... Это не вписывается в методологию разработки облачных приложений и я бы не рекомендовал так делать. Вместо if env prod, лучше поставить конфигурацию из env переменных или config файла, это позволит запускать сервис на любых окружениях с любой конфигурацией. Это может быть полезно, например при разворачивании окружения для нагрузочного тестирования или интеграционного. https://12factor.net/config

Опять же с моей скромной точки зрения, разработку сервиса стоит начинать с паттерна graceful shutdown

А где вы обычно смотрите трейсы в вашей системе?

OpenTelemery поддерживает множество экспортеров. https://github.com/open-telemetry/opentelemetry-go/tree/main/exporters - Jaeger, OTPL, stdoutrace, zipkin.

В примере, который прикреплен в конце для трассировки используется Jaeger.

В OpenTelemetry есть такой термин как Instrumentation, это по факту набор готовых middleware для различных популярных библиотек. Для http, gPRC тоже есть - вот ссылка на примеры его подключения https://github.com/open-telemetry/opentelemetry-go-contrib/tree/main/instrumentation/google.golang.org/grpc/otelgrpc/example

https://github.com/open-telemetry/opentelemetry-go-contrib/tree/main/instrumentation/net/http

После подключения этого инструмента к http, gRPC, вы сразу увидите все трейсы ваших запросов, но они будут не связаны. Для того что бы их связать нужно просто инициализировать propagation, как показано в статье. Сам instrumentation уже внутри своей реализации производит Inject и Extract.

А что значит "событийно ориентированный рантайм"? Как вы реализуете свою систему полностью зависит от вашего проекта. Обычно в самом простом случае MQ выступает в роли шины данных между сервисами. У вас может быть rabbitMQ, Kafka это не имеет никакого значения, потому что принципы context propogation в open telemetry остаются такими же. В гайде на примере кода я показал, как ими пользоваться. Если вас интересует настройка инфраструктуры, загляните в пример проекта на GitHub-е, который я прикрепил к статье.

В код вашего проекта на Go. Теги "Go, программирование" и в конце статьи ссылка, на пример реализации. Полный проект с инструкцией, как его развернуть локально, со всей нужной инфраструктурой: jaeger, NATS.

Немного не понятен выбор технологий в статье. Есть же SSR frameworks типа next.js например... В практике я пробовал SSR и делали мы это исключительно для SEO, пришлось повозиться и это не так просто, как кажется. В коде появилось куча if-ов, что исполнять на стороне сервера, а что исполнять на стороне клиента, возможно дело было в нашей структуре проекта. В общем, если хочется SSR, лучше подумать 100 раз и сделать статикой, через тот же gatsby, а если нужен backend for frontend (BFF), то SSR это не про это.

Спасибо за ответ :) Когда долго чем-то занимаешься забываешь, что очевидные для тебя вещи не очевидны для других.

По поводу логов, логи важны, логи нужны, но они так же могут являться большой проблемой для производительности это факт. Поэтому как минимум нужно поддерживать различный log level в своих сервисах (debug, warning, info, error), ещё лучше использовать специализированные пакеты для логов в которых был сделан упор на производительность. Так же для меня очевидно, что разработка идёт в разных изолированных окружениях local, dev, test, stage, prod. Так вот если на local, dev, test допускается использовать log level = debug, то для stage и prod это уже не допустимо. Так же как не допустимо вылить на stage сервис с memory leak.

Мой совет по debug logs на функции, касается только local и dev окружения. Для stage и prod это не допустимо.

Привет минуса :) Как я написал в последнем абзаце "дать конкретные советы невозможно, каждый проект индивидуален", описать все возможные кейсы не реально. Например Мартин Фаулер издал 8 книг с 1996 года в каждой из которых по 400-500 страниц примеров кода и продолжает вести свой блог по рефакторингу и архитектуре. На сайте govnokod.ru сейчас 28 000 записей :)

"консольного наблюдения достаточно" - если мы говорим про команду top, её большой минус это отсутсвие визуализации изменения значения во времени. Можно пропустить тот момент когда было 10 мегабайт потом стало резко 300, потом 20, но 20 ведь тоже не нормально должно же быть 10. Или как понять что происходило с памятью в течении 2х месяцев эксплуатации сервиса в продакшене, кушает ли он память?

Я могу лишь дать базовые советы по отладке. Пишите debug логи в начале и конце функции, например через defer, так вы сможете отследить ее завершение и понять по логам сервиса при каких обстоятельствах он упал или память начала расти. Не стесняйтесь в лог выводить переменные, например идентификатор клиента, который подключился, параметры "флаги" запуска сервиса. Обычно в логах присутствует timestamp, посмотрев на графике, когда начался рост и почитав логи в ELK за этот период, можно будет понять, что примерно происходило в программе и попытаться воспроизвести этот сценарий. Внимательно проверяйте все ли вы открытое закрываете, особенно это хорошо проявляется при отладке graceful shutdown. Например известный кейс с "close response body". Если интерфейс предоставляет метод close или подобный возьмите за правило после его инициализации писать defer *.close()

Продолжать можно бесконечно долго :)

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

С развитием навыков и знаний (про SOLID про DRY, TDD, BDD, DDD и тд) у тебя уже изначально не будет получаться «лапшекод», но нужно понимать грань между временем решения задачи и времени на проектирование этого решения. В случае если ты обычный разработчик а не архитектор, если время проектирования решения занимает больше чем время решения — лучше выбрать монолит, грубо говоря если сходу не можешь прикинуть как что должно быть правильно — накидай монолит, который в этот же день начни раскидывать по «правильному», главное что бы он заработал и решал поставленную задачу :)
«Крайние точки зрения всегда ошибочны! Рассматривайте проектирование как грязный, неряшливый эвристический процесс» — С. Макконнелл

«чем догматичнее вы будете в отношении методики проектирования, тем меньше реальных проблем решите» — Ф. Дж. Плоджер

Не осилил статью, но расскажу немного про преждевременную оптимизацию. На практике очень часто бывает так что требования меняются по ходу разработки и жизни проекта. Вы много часов потратите на "переиспользуемые" блоки, а потом требования изменятся. Напишите сначала монолит, который возможно и некрасивый, но работает. После того как проект устаканится или вам выделят время на рефакторинг занимайтесь им. Позже с опытом у вас само собой появятся эти "перписпользуемые" практики написания кода.
Как по мне TS незаменим на бекенде, для компонентов если они "правильно" написаны (pure function) TS оверхед, который усложняет и замедляет разработку. ИМХО.
Если вас действительно интересует качество вашего кода, читайте книжки: "совершенный код", "чистый код". "Рефакторинг" Фаулера кстати очень занятная книга по теме.

Зачем тащить в проект лишнюю зависимость, если ты в состоянии написать нужную тебе реализацию?

Скорость чтения/записи на диск это то во что ты упираешься пиши хоть на ассемблере. Если твоя программа работает с файлами, выше этой цифры не прыгнешь. Если опускаться на уровень операционной системы она тоже работает с файловой системой, например когда ты запрашивает новый срез memory mapped файла. Не возьмусь утверждать, но вроде винда скидывает дамп памяти на диск при выходе за границы виртуальной памяти процесса. JS код это очень-очень много мелких файлов (node_modules). Билд на SSD и HDD небо и земля, личный опыт.

Работаю с 16 наверстал после 25 :) Точнее выгорел к 25.
Ну и зачем? Ребята из root-me старались, подготавливали материал, а вы делаете «решебник». Смысл то в том что бы побудить людей к исследованию и изучению чего-то нового, а вы убиваете всю интригу.

Information

Rating
Does not participate
Location
Бобруйск, Могилевская обл., Беларусь
Date of birth
Registered
Activity