Наши стандарты DX

4b6ee4772a118dd5680760ef0a4f1729.jpg

Философ был свободен от следующих 4-х предметов: предвзятого взгляда, уверенности, упрямства и эгоизма (Конфуций)

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

Суть

Имеется некий опыт работы в ключе «Пиши столько кода, чтоб потом писать его меньше» — и, как оказалось, при соблюдении некоторых правил, это работает. Здесь автор пробует формализовать тезисы своего подхода к успешному DX в духе продуктовых Enterprise, исходя из личного опыта. Некоторые из них выглядят как прописные истины, но, зачастую, придя на проект, ловишь себя на мысли «Судя по результату, здесь не было таких правил»…

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

Ремарка насчёт организации архитектуры абстрактного проекта в абстрактной компании

Отвечая на вопрос «Какова успешная архитектура на Ваш взгляд?», необходимо учитывать специфику Бизнеса в рамках которого происходят процессы. К примеру, для одних в порядке вещей содержать штат из сотрудников разных отделов: DevOps, Backend, Frontend с разделением соответствующих обязанностей; Для других существует необходимость содержать минимальный штат из двух человек, которые должны поддерживать работу всех систем с не менее высокими требованиями по отказоустойчивости и масштабируемости. В этих двух случаях мы можем получить существенные различия по архитектурным решениям, но в целом, любое техническое решение не должно противоречить требования Бизнеса (устойчивость, масштабируемость, гибкость на необходимом и достаточном уровне), причем, вопросы DX при этом не должны задевать Бизнес — это и будет самый короткий ответ на вопрос по «Идеальной архитектуре».

#1 Простая сборка — лучшая сборка

Первое правило хорошего DevOps инженера: «Чем проще — тем лучше»

  • Запуск / Сборка / Деплой должны запускаться одной командой

  • Сборка и раскатка всех режимов (Development / Staging / Production) должна быть настроена и автоматизирована до начала разработки фич

  • Сборка должна быть максимально абстрагирована от деплоя. Все что можно вынести в переменные среды для конкретной сборки — должно быть вынесено

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

#2 Помните про абстракцию

  • 2.1 Соблюдайте высокий уровень абстракции. Для удобства переиспользования компонентов и соблюдения атомарности.

  • 2.2 Сохраняйте контроль над Бизнес Логикой

    Соблюдать разделение бизнес-логики веб-приложения на «слои» — мастхэв для масштабируемости и устойчивости к изменениям. Здесь нужно определить значимость центров принятия решений при постановке ТЗ (что бы это ни значило, постараюсь объяснить ниже по тексту) — теоретически, именно это должно повлиять на выбор стека технологий на ранних этапах.

    Иными словами (в более широком смысле), расставляйте приоритеты правильно (убывание приоритета вниз по грейду):

    1/ Деньги в глазах Бизнеса;
    2/ Живучесть Бизнеса глазами абстрактных инвесторов (вера в продукт и другие ментальные вещи, не касающиеся разработки);

    3/ Управление логикой Продукта на уровне Менеджмента, а так же необходимая масштабируемость и гибкость Продукта — глазами Менеджмента (тот слой компании, который ставит задачи разработчикам);
    4/ [Вы здесь] DX глазами Разработчиков;
    5/ Ценность Программного Продукта (в виде физического набора текстовых файлов исходного кода, которые никому не нужны без адекватного DX, а их отсутствие принесет ущерб Бизнесу) — глазами абстрактного бухгалтера, выдающего зарплату;

    Имеющее более низкий приоритет не должно быть важнее того, что выше — иначе Бизнес Вам скажет, что ему это не нужно. К примеру, от удобства разработки не должно страдать управление Проектом, а значит выбор стека технологий должен быть соответствующий задачам Бизнеса и т.д. Ещё пример: Удобство разработки Продукта, не должно обходиться дороже, чем та прибыль, которую имеет Бизнес с Продукта (случай, когда Продукт живёт за счёт другого Продукта будем считать исключением).

    ☝️ Описанное выше, как изначально предполагалось, должно было иллюстрировать превосходство Управления Проектом глазами Менеджера над Developer Experience глазами Разработчиков. «Не делайте из еды культа», как говорил Остап Бендер. Однако со временем, получив больше контекста, мысль разрослась, и может выглядеть более перегруженной, чем предполагалось изначально… Но слов выкидывать пока не стал))

Какой результат ожидается

  • Удобство переиспользования кода;

  • Быстрое решение задач Бизнеса в дальнейшем;

  • Бизнес про Вас не знает и Вы ему не мешаете;

#3 Настройте внешние механизмы отладки

  • 3.1 Формулируйте требования

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

    • Позитивные кейсы (клиент дошел до конца успешного сценария);

    • Негативные кейсы (к примеру, ошибка сценария);

    • Все остальные кейсы, вызывающие вопросы;

    Есть много способов узнать текущее состояние клиента с целью анализа, к примеру:

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

  • 3.2 Формулируйте ограничения

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

    • Кэш (практически, без ограничений)

    • Google Sheets (ограничение 50K символов в ячейке + 300 ивентов в минуту на проект / 60 ивентов на пользователя в проекте) See also

    • Telegram API (10K символов в сообщении + самописная очередь с ограничением по частоте отправок)

    На каждом этапе ивент может «отвалиться» — об этих случаях разработчику также надо быть в курсе (см. пункт 4.1).

  • 3.3 Ничто не вечно

    Если внешний механизм отладки недоступен — приложение должно работать.

  • 3.4 Управляйте метрикой

    Отключайте метрики для устаревших версий. Логика управления поддержкой логов для конкретных версий клиентского приложения должна быть внешней.

  • Зачем это все?

    См. пункт 4.

#4 Настройте внутренние механизмы отладки

Пишите код так, чтоб Reverse Engineering был не нужен! Иначе, следующий разраб может сделать харакири в лучшем случае — себе, в худшем — начать искать Вас.

  • 4.1 Все данные должны быть проверены

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

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

  • 4.2 «Явное лучше неявного»

    • Типизируйте все, что можно

    • Покрывайте тестами то, что нужно

    • Держите пользователя в курсе происходящего (см. пункт 4.1)

  • 4.3 Предусматривайте дебаг-режим кода

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

  • 4.4 Предусматривайте пользовательский дебаг-режим

    А это нечто другое — речь про включение / отключение отладочного UI клиента. Желательно, чтоб это не требовало перезагрузки страницы (к примеру, в тех проектах, где это возможно, для включения такого режима, я использую хэш роутинг с параметром). Что я включил бы в этот пункт:

  • 4.5 Отправляйте данные (логи) для анализа

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

    • eventType — Тип ивента (default|info|warn|danger|success)

    • appVersion — Client app version from package.json

    • details — Объект с целевой информацией (к примеру, текущее состояние приложения в формате json)

    • uniquePageLoadKey — Ключ, который был сгенерирован при загрузке страницы

    • gitSHA1 — Хэш коммита, соответствующий сборке

    Все данные, которые можно вынести во внешние службы, должны быть вынесены:

    • ts — Время прилёта ивента

    • ip — IP клиентской подсети

    • userAgent — User-Agent from headers

    • clientReferer — Client-Referer from headers

    При включенном дебаг-режиме советую отображать состояние лога, как следствие пункта 4.4.

Какой результат ожидается

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

#5 Выполняйте сложную работу один раз

  • 5.1 Второй раз всегда должен быть проще

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

    В качестве примера, частный случай из практики (в контексте паттерна FSM): Есть необходимость дебажить кейс из двух процедур, вторая их которых должна быть вызвана по некоему неочевидному условию:

    1/ В контексте стейт-машины создаем промежуточный шаг с отключенной настройкой «Пропустить этот шаг» и кнопками «Продолжить» для различных сценариев;
    2/ Дебажим;
    3/ Включаем настройку «Пропустить шаг»

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

  • 5.2 Отладка должна быть информативной

    Используйте UI для отладочного режима с информативными сообщениями. Я имею ввиду не просто отображать факт ошибки (см. пункт 4.1), а делать это так, чтоб информация о ней была максимально исчерпывающей. Клиент (в частном случае, разработчик) должен понимать, что делать с этой информацией. Именно выполнение этого пункта даст моральное право написать клиенту «Мы уже работаем над этой проблемой!»

    Что может быть важно в плане практической пользы:

    • Все сервисы должны иметь общий протокол информирования об успехе или ошибке. К примеру, оглядываясь на fb, можно увидеть для себя хороший и простой пример: { ok: boolean; message?: string; }

Зачем это все?

Больше работы — меньше кода.

3e204344cade50ff810f5c870c1b9561.jpg

© Habrahabr.ru