Как увеличить качество технических решений?

Мне довелось поработать с очень разными командами, как в стартапах, так и в big tech. Удивляет, что даже сильные команды нередко создают переусложнённые решения. Отдел разработки с опытными сотрудниками может допускать значимые ошибки в проектировании или реализации. Я заметил, что между организацией работы команды и переусложнёнными решениями есть связь.

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

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

Первое, с чем я столкнулся, — это отсутствие ясного способа работы с компонентом. Полноценной инструкции не было. Сразу запустить компонент не удалось: пришлось отвлекать автора проекта и "лезть под капот". Выяснилось, что у компонента нет удобного интерфейса для интеграции. Данные для предварительной настройки физического сервера раздаются через отдельный веб-сервер. Обработка данных и логика настройки сервера написаны на Bash, причём скрипт состоит из более чем 800 строк и выполняется в live-окружении ISO-образа.

Компонент можно было реализовать значительно проще. Например, не обязательно поднимать веб-сервер для раздачи настроек. Да, есть сценарии, когда веб-сервер уместен, но не в нашем случае. Гораздо проще было бы реализовать логику на Python и выполнять настройку сервера через SSH.

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

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

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

  2. Отсутствие артефактов проектирования.
    Без диаграмм и схем сложно организовать продуктивное обсуждение дизайна проекта. Скорее всего, при обсуждении кто-то обратил бы внимание на веб-сервер и задал вопрос: "Зачем он здесь? Это же можно сделать гораздо проще, не добавляя лишние элементы в компонент". Веб-сервер нужно обслуживать, и это создаёт избыточность. На основе таких вопросов могла бы возникнуть конструктивная дискуссия, которая предотвратила бы сложность.

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

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

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