Процесс разработки программного обеспечения сводится к тому, что разработчики пытаются что-то создать и донести до пользователя. Неотъемлемой частью этого процесса являются ошибки и проблемы. И нет ощущения, что что-то изменится в ближайшее время. Это правила игры, под которые нужно подстроиться. Далее будет рассказ о том, как это сделать.


Разработчик Клиент

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

  • Сформировать требования к продукту
  • Разработать продукт
  • Отправить клиенту
  • Дождаться пока клиент посмотрит
  • Дождаться пока клиент даст фидбек

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

Разработчик Тестировщик

Смена методологии разработки - это отдельная история, которая сейчас останется за скобками. Вместо этого можно сконцентрироваться на последних двух пунктах. Они перекладывают ответственность на клиента по передаче фидбека. Хотя клиент ничего не должен разработчику, он доберётся до продукта, когда ему будет удобно, даст фидбек, если будет желание. Первым шагом уменьшения цикла фидбека может выступать добавление промежуточного звена между - тестировщика. Задачей тестировщика является проверка сценариев и поиск проблем. С точки зрения разработчика, тестировщик - это новый клиент. Разработчик взаимодействует с ним для более быстрого получения фидбека. На этом шаге метрикой оценки улучшения цикла фидбека является максимизация процента багов, которые найдутся тестировщиками, а не клиентами. Другие разработчики также могут быть привлечены для повышения качества. Обычно это делается при помощи Code review. В процессе ревью другой разработчик может заранее найти проблемы, в том числе те, которые сложно находить тестировщикам.

Разработчик Интеграционные тесты

Перекладывание ответственности с клиента на тестировщика или другого разработчика сокращает цикл фидбека, но есть две проблемы:

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

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

Алгоритм такой:

  • Разработчик вносит изменения
  • Происходит сборка продукта с этими изменениями
  • Запускаются интеграционные тест

Если тест найдёт ошибку, то уведомит об этом разработчика. Цикл обратной связи сильно сократился. Но вместе с сокращением цикла также сокращается скоуп сценариев, которые можно рассматривать. Некоторые сценарии сложно автоматизировать, создать для них интеграционный тест.

Разработчик Continuous integration

Все выше описанные подходы сводились к тому, что разработчик вносит свои изменения, а после начинается поиск проблем. Следующий шаг к сокращению цикла фидбека - это Continuous Integration. Идея Continuous integration заключается в постоянной интеграции нового кода. Кодовая база должна иметь набор тестов или других способов верифицировать корректность кода. Каждое новое изменения должно проходить через этот набор. Без CI продукт сломан до тех пор, пока кто-то не докажет, что он работает. С CI работоспособность проверяется на каждом шаге. Пример реализации CI: Github Pull Request + Github Actions и Azure DevOps Pull Request + Azure DevOps Pipelines. Использование этих инструментов подразумевает такой воркфлоу:

  • Разработчик создаёт свои изменения локально
  • Разработчик создаёт Pull request и отправляет его
  • Система запускает скрипты для проверки новых изменений - сборка, запуск тестов
  • После успешного прохождения проверок код может быть отправлен на ревью

Такой подход ещё больше сокращает цикл фидбека - он получается до того, как изменился продукт. Основные источники фидбека - это проверки, которые были добавлены на CI. Чем их больше и чем они строже - тем больше фидбека. Обратная сторона подхода - увеличение времени, которое нужно для внесения изменений. Если в продукте много тестов и все они будут запускаться перед каждым изменением, то это может длиться несколько часов. Поэтому в CI обычно запускаются функциональные тесты или юнит тесты.

Разработчик Компилятор

Один из самых минимальных циклов фидбека - это фидбек от компилятора/IDE. IDE сообщает о написании не корректного кода сразу, компилятор - при попытке скомпилировать проект. Такой короткий цикл фидбека позволяет разработчику узнавать о проблемах в процессе написания кода, когда он ещё в контексте происходящего, сразу корректировать код. Например, компилятор умеет в очевидных местах находить вероятные Null reference exceptions. Если разработчик увидит предупреждение об ошибке во время написания кода, то сможет сразу исправить, а не ждать, пока код пройдёт CI.

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


Какие книжки подсматривал при написании: