Как начать разработку, ориентируясь на качество

0
229
views

Перевод статьи «How to start a software project with a quality mindset».

Начинаем разработку, ориентируясь на качество

Создание качественного программного обеспечения это непростая задача, требующая много практики и опыта.

Такие важные действия, как модульное тестирование или составление документации, все еще считаются многими разработчиками чем-то вроде «задач со звездочкой», и когда приближается дедлайн, их сокращают в первую очередь.

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

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

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

«Менеджеры продуктов должны понять, что поддерживаемость это критически важная часть выпуска продукта, потому что позволяет вам продолжать выпускать все новый функционал. Технический долг накапливается, а кроме того, по нему набегают «проценты». Поэтому, в каждом случае, когда вы хотите «срезать» путь, чтобы выпустить какие-то фичи, помните о том, что вы берете взаймы у будущего», – Брайан П. Хоган.

Качество это не та вещь, которую можно легко добавить позже.

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

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

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

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

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

Ставим качество во главу угла еще на старте

Определение процесса разработки, инструментария и т. п.

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

Где будет храниться код приложения и побочные продукты? Как будут отслеживаться проблемы? Каким будет процесс внесения новых изменений в кодовую базу? Должны ли изменения проходить процедуру ревью? Из каких шагов будет состоять эта процедура? Какая модель Git flow будет использоваться? Кто может выступать контрибутором и выполнять слияние кода?

На все эти вопросы нужно дать ответы и задокументировать их.

Заложение основ хорошей документации

Документация очень важна, но порой ее считают чем-то вторичным. Она становится еще важнее, когда вы работаете в команде, над open source проектом или когда создаете ПО, которое будет использоваться при создании других программ.

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

Для начала можно начать с самого минимума. Файл «README» будет представлять ваш проект, объяснять, как запустить его локально и как можно принять участие в разработке этого проекта. Далее вы должны быть готовы документировать все: ваш технологический стек и инструменты, процедуры разработки, стандарты написания кода, важные архитектурные и технические решения и т. д.

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

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

Документация помогает поддерживать качество кода

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

Что касается более технической документации, я бы сказал, что здесь самый простой способ начать – писать ее в Markdown-файлах в папке «docs» репозитория вашего проекта. Вы можете оформить ее в виде отдельного сайта, используя что-то вроде VuePress или Gatsby. Преимущество такого подхода в том, что документация находится близко к коду и доступна для системы контроля версий, а это помогает разработчикам поддерживать ее в актуальном состоянии.

Для более «общей» документации или документации продукта одним из самых популярных корпоративных инструментов является Confluence, но также есть много «wiki»-систем, которыми вы можете воспользоваться. Большую популярность приобретает Notion. Также интересным вариантом является Outline (open source).

Если вы создаете API, обратите внимание на OpenAPI Specification.

Определение и внедрение стандартов написания и оформления кода

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

Кому не случалось просматривать пул-реквест, который вроде бы был очень маленькой фичей, а в конечном итоге затронул множество файлов, потому что разработчик настроил свой редактор на использование 2 пробелов, в то время как остальные разработчики использовали 4 пробела? Подобное вносит большую сумятицу в вашу процедуру ревью кода и приводит к бесполезным изменениям в кодовой базе.

Не нужно изобретать велосипед. В большинстве языков программирования есть какие-то рекомендации относительно стиля оформления кода. В PHP есть PSR-2, в JavaScript – AirBnb или Standard, в Python – pep8.

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

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

Для выявления отклонений от стандартов можно использовать ESLint для Javascript или PHP_CodeSniffer для PHP. Некоторые инструменты, такие как Prettier, gofmt или PHP-CS-Fixer, могут даже автоматически форматировать ваш код и исправлять недостатки в соответствии с принятыми стандартами.

Убедитесь, что все ваши разработчики знакомы с этими инструментами и запускают их в своей среде разработки и IDEs. Также следует включить проверки в вашем Delivery Pipeline (об этом позже).

Стандарты кода и его качество

Хороший способ убедиться, что каждый коммит, сделанный в репозиторий, соответствует принятым правилам, это использование git hooks для запуска этих инструментов при каждом коммите или push-е. Я недавно нашел pre-commit, который помогает настраивать git hooks в вашем проекте. Может, вы тоже захотите попробовать.

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

Можно пойти даже дальше, определив стандарты оформления или другие вещи вроде сообщений коммитов или логов изменений при помощи таких инструментов как Commitizen или Conventional Changelog.

Помимо стандартов стиля, также можно определить стандарты, относящиеся скорее к архитектуре. Например, принять, что проект должен следовать «шестигранной» архитектуре.

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

Чтобы облегчить создание проектов и иметь все эти инструменты в настроенном виде, в полной готовности к началу разработки, можно создать некие базовые шаблоны проектов, которые разработчик сможет клонировать. GitHub только что представил шаблоны репозиториев. Также для этих целей можно использовать такие инструменты как SAO или Yeoman.

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

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

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

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

Каждый язык программирования имеет какие-то инструменты статического анализа. Уделите время изучению и настройке их в своем проекте.

Если вы хотите пойти дальше и получить более подробный обзор и разные показатели качества кода в вашем проекте, обратите внимание на такие инструменты как SonarQube, Code Climate или Codacy.

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

Качество кода

Набор автоматизированных тестов

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

Такие подходы как непрерывная доставка возможны только при хорошем наборе автоматизированных тестов.

Автоматизированные тесты (более конкретно – модульные тесты) это также хороший «двигатель» написания лучшего кода, поскольку они будут «вынуждать» вас писать более простой и несцепленный код, а также применять популярные шаблоны проектирования вроде Dependency Injection и прочие принципы S.O.L.I.D для обеспечения тестируемости кода.

Тесты также могут использоваться как одна из форм документации существующего функционала и всех возможных сценариев и use cases.

Начните с модульных тестов, затем добавьте интеграционные тесты (тесты сервисов) и пару сквозных тестов, чтобы гарантировать, что ваше приложение может обслуживать запросы.

Создайте простой тест «hello world» для каждого типа, прежде начать добавлять функционал. Это гарантирует, что вся ваша инфраструктура будет настроена должным образом для выполнения этих тестов, а это ускорит работу в дальнейшем.

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

Среда разработки

Среда разработки

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

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

Я считаю, что у вас должна быть возможность настроить среду разработки, просто выполнив одну команду. Сегодня это гораздо проще сделать, благодаря таким инструментам как Docker и Docker Compose, дополненным Makefile или какими-нибудь shell-скриптами.

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

Нужно стремиться к тому, чтобы ваша локальная среда была как можно больше приближена к продакшен-среде. Если в продакшене вы используете Docker, вы можете воспользоваться преимуществами Docker Multi stage builds и использовать те же базовые образы, которые используются в продакшене.

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

По возможности, регулярно тестируйте свой скрипт на новой машине (можно на виртуальной). Ха! Вы можете даже добавить какие-то автоматизированные тесты для проверки, правильно ли запускаются сервисы приложения. Нет предела совершенству!

Но в понятие «настройка среды разработки» входит не только само приложение. Уделите время тщательной настройке своего редактора кода / IDE и всех дополнительных инструментов. Многие IDE имеют конфигурационные файлы, которыми вы можете делиться с командой через систему контроля версий. Таким образом можно поддерживать синхронизацию глобальной конфигурации и единообразие в инструментах всех членов команды.

Конвейер доставки (Delivery Pipeline)

Давайте теперь поговорим о пропущенном куске головоломки, который скрепляет все уже рассмотренные нами части, – о конвейере доставки.

Конвейер доставки определяет все стадии, которые должен пройти ваш код, от коммита в системе контроля версий до продакшена.

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

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

В зависимости от ваших нужд вы можете позже добавить и другие стадии, например, тестирование безопасности и производительности.

Конвейер доставки

Стадия сборки

Здесь нет ничего необычного. Н этой стадии ваш код забирается из системы контроля версий и собирается в пригодный для деплоймента продукт. Это может быть образ docker, tarball, rpm и т. д.

Стадия статического анализа

На этой стадии код проверяется на соответствие стандартам и отсутствие проблем в структуре кода. Здесь применяются все те инструменты, о которых мы говорили ранее.

Стадия модульного тестирования

На этой стадии следует запустить ваши модульные тесты. Даже если вначале у вас есть только тест «hello world», наличие его в конвейере позволит вам в будущем быстрее создать лучший тест на его основе, поскольку инфраструктура для запуска тестов будет уже готова.

Стадия интеграционного тестирования

На этой стадии запускаются ваши интеграционные тесты или тесты сервисов.

Здесь вам могут понадобиться какие-то дополнительные сервисы. Например, для проверки интеграции с базой данных вам понадобится сама база данных.

Большинство современных инструментов CI / CD поддерживают Docker, так что вы сможете с легкостью размножить, например, контейнер MySQL, чтобы использовать его в ваших тестах.

Стадия приемки

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

Стейджинг можно также использовать для какого-то мануального тестирования или тестирования UI, или чтобы поделиться каким-то незаконченным функционалом.

Стадия деплоймента

После прохождения всех предыдущих стадий ваш код готов к деплойменту в продакшене.

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

Для определения конвейера доставки есть множество прекрасных инструментов. Часто для этой цели используется Jenkins, но я предпочитаю более современные инструменты, такие как CircleCI, GitLab или Drone CI.

GitLab и Drone это инструменты с открытым исходным кодом. Вы можете установить их в вашей собственной инфраструктуре, но если вы только начинаете, стоит обратить внимание на их облачные решения.

GitLab это решение из серии «все включено», поскольку предоставляет вам систему контроля версий, панели проблем, конвейер непрерывной интеграции, интеграцию с Kubernetes для деплоймента и многое другое. Это отличный инструмент для быстрого старта.

Если хотите подробнее изучить, как правильно создавать конвейер непрерывной доставки, почитайте эти статьи:

Дополнительно: ищите любые возможности для автоматизации

Обратите внимание на каждый процесс, который вы выполняете вручную и при этом все время повторяете, и поищите возможность автоматизировать выполнение этих задач. С этой целью можно пользоваться bash-скриптами (для запуска тестов или скачивания дампов базы данных), GitHub WebHooks, чатботами, а также комбинациями нескольких инструментов и APIs. Нет ничего невозможного.

Старт

Заключение

На поддерживаемость и качество проекта очень сильно повлияет то, как вы его начали.

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

Нужно ли все описанное в любом проекте? Как и во всем, что касается разработки ПО, единственно правильного решения не существует. Следует учитывать множество факторов. Если это очень маленькое приложение или MVP, то может, так много и не нужно. А вот для проекта, который должен быть очень надежен или, по вашим прикидкам, существенно вырастет с годами, – все это точно необходимо.

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

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

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

ОСТАВЬТЕ ОТВЕТ

Please enter your comment!
Please enter your name here