Мои лучшие практики
Что я считаю лучшими практиками и чего придерживаюсь.
Многое из нижеследующего вдохновлено The Twelve‑Factor App и преследует ту же цель - предложить методы создания приложений которые:
- Способствуют сохранению динамики роста приложения с течением времени
- Сопротивляются эрозии программного обеспечения
- Требуют минимум затрат времени и ресурсов новых разработчиков
- Обладают максимальной переносимостью между средами выполнения не смотря их развитие
- Позволяет использовать непрерывное развёртывание (continuous deployment) для сокращения периода обратной связи от пользователя
- Могут масштабироваться без существенных изменений в инструментах, архитектуре и практике разработки
Ниже изложено в соответствии со следующей структурой:
- Цель. Для чего подходит инструмент.
- Концепция. Абстрактные подходы, выявленные опытом.
- Принципы. Утверждение, пример, которое позволяет действовать эффективно в определенной ситуации.
-
Комментарий может раскрывать причину происхождения принципа
Общее
Принципы
- Придерживаясь подходов, которые используются сообществом или создателями, мы сильно снижаем onboarding time.
- Сложно делать то, что нужно. Еще сложнее не делать того, что не нужно.
- Хорошо работает только то, что естественно и интуитивно.
- Костыль появляется там, где мы боремся со следствиями вместо устранения причины.
- Автоматизация помогает там где рутина или дорогая ошибка.
Документация
Цель
- Увеличить удобство использования ценой разработки
- Снизить порог входа разработки
Концепция
- Требуется там, где истина в не удобном виде
- Самая бесполезная документация - не актуальная
- Чем дальше от точки истины тем быстрее теряет актуальность
README.md
С чего начать использование и troubleshooting.
Здесь так же может находиться ссылка на /docs/usage_guide/
если первичная
информация слишком обширна. Типичные примеры:
- Описание конфигурации
- Как интегрировать со смежными технологиями
- Лучшая инструкция по использованию - удобный интерфейс, поэтому здесь нет информации о функционале приложения. Лучше всего ее располагать непосредственно в приложении. Например, если это консольная утилита, то
some_binary --help
будет подходящим выбором. Такой метод является распространенным и пользователю не прийдется переключать окна. Если приложение имеет графический интерфейс и его невозможно сделать интуитивным, то стоит позаботиться о наличии раздела “Справка”. Хранение инструкции пользователя в приложении так же решает проблему версионирования документации.- Истина в коде, пользователь использует непосредственно приложение.
CONTRIBUTING.md
Как разрабатывать.
Здесь так же может находиться ссылка на /docs/contributing/
если
соглашений настолько много что не удобно читать. Типичные примеры:
- Соглашения по документации (На какие вопросы должна отвечать документация)
- Как пишем код?
- Как именовать методы?
- Как добавить новый модуль?
- Какие инструменты используются для постройки и выполнения других задач?
- Как пишем тесты?
- Как структурируем тесты?
- Как управляем релизами?
- Как именовать релизы?
- Как управляем конфигурацией?
- Как публикуем (deploy)?
- Где конфигурации среды исполнения и инфраструктуры?
- Где мониторинг?
- Как собираем баги? Где можно создать feature request?
- Лучшее соглашение - автоматизированное. Сняв с разработчика обязанность помнить и исполнять тьму соглашений, он сможет сконцентрироваться на самом главном.
- Истина в коде. Пользователь создает код.
*doc
Как использовать код.
- Использование в интерфейсах
- В классах только аннотации для IDE
- Лучший код расскажет сам как его использовать и расширять.
- Истина в коде. Пользователь использует и создает код.
Wiki
Информация, истина о которой находится у бизнеса (Доменного эксперта)
- Здесь сценарии использования приложения. Описание реакций приложения на внешние события.
Планирование
Цель
Оценить рациональность проекта. Синхронизировать ожидания поставщика и получателя.
Принципы
- Оценка задач по времени не значительно отличается в точности от оценки по количеству.
- Хороший план начинается с цели, которую можно точно определить одним предложением.
Код
Цель
Хороший код поддерживает динамику внесения изменений с ростом приложения. (Сопротивляется эрозии)
Концепция
Хороший код обладает свойствами:
- Гибкий — Быстро расширять, минимум действий кроме требуемых.
- Простой — Легко понять что делает код, и как расширить функционал.
- Стабильный — Тестируем и покрыт тестами.
- Быстрый прототип — Чтобы достичь первого результата, нужно сделать минимум.
Принципы
- Параметры вносят неопределенность, поэтому они только там где неопределенность.
- Fail Fast!: Лучше узнать о баге на этапе компиляции, чем когда на него натолкнется пользователь.
- Хорошая ошибка расскажет как от нее избавиться.
- Для передачи даты и времени есть широко распространенный ISO8601 RFC3339
- Если ставишь deprecated, то объясни в пользу чего.
- Time is ambigous, timestamp and duration - not. Avoid using “time”.
- Make your classes always final, if they implement an interface, and no other public methods are defined link
- Robustness principle simplifies communications in distributed systems
- Логируя разветвления, проще понять поведение в боевой среде PokeMonitor
- Хорошее именование инкапсулирует логику, соответствует принятым практикам(паттернам)
- Если IDE регламентирована, то отдавая приоритет инструментам автоматического рефакторинга IDE, увеличиваем гибкость
- Чем чаще код изменяется тем проще с ним работать link
- Распределенные системы не панацея - у них свои недостатки link
Постройка (не компиляция)
Цель
Получить преимущества ценой предварительной обработки кода
- Возможность использовать сторонние решения
- Валидация на основе системы типов
- Обфускация
- Сжатие кода
Концепция
Хорошая постройка:
- После постройки можно доставить в любое окружение с любой конфигурацией без перестраивания
- Чем больше можно зафиксировать тем быстрее и стабильнее. Уровни: Код, среда исполнения, инфраструктура, task runner.
Принципы
- В контейнере должно быть все что нужно для его полноценной работы во всех типах окружений
Автоматизированное Тестирование
Цель
- Убедиться что в процессе внесения изменений мы изменили только желаемое
- Для модульных: Упростить написание стабильного кода
Концепция
Хорошие автоматизированные тесты:
- Ясно отражают функционал
- Ломаются только при поломке функционала
- Их быстро писать
- Быстро выполняются
Принципы
- Уровень регресса тестирования зависит от того, как часто мы хотим выпускать релизы
- Хорошие тесты проще писать прежде кода
Обеспечение качества
Цель
Улучшение опыта использования приложения
Концепция
Аспекты качества приложения:
- Функционал. Насколько широко приложение покрывает бизнес.
- Производительность. Как долго пользователю приходится ожидать реакции. Для веб можно мерить, например, в rps.
- Безопасность. Насколько приложение защищает пользователя от совершения ошибки о которой он не знает. Например введение пароля звездочками.
- Защищенность. Что нужно предпринять и за какое время чтобы получить доступ к информации приложения которой ты не должен был обладать.
- Портируемость. На каких устройствах и в каких окружениях приложение может исправно работать. Для веб приложений, например, возможность запускать приложение на платформе для разработки, для тестирования.
- Восстанавливаемость. Сколько нужно секунд чтобы приложение восстановило свою работоспособность.
Принципы
- Защищенность системы равна минимальной защищенности компонентов системы.
- Контроль защищенности зависимостей, например roave/security-advisories, улучшает защищенность
Управление релизами
Цель
Предоставить пользователю продукт в варианте, который пользователь ожидает.
Концепция
- Содержит достаточно для замены.
- Версионирование предсказуемо для пользователя.
Принципы
- Релиз это код прошедший постройку + конфигурация
- Версионирование для библиотек всегда Semantic Versioning
- Как часто мы выпускаем релизы зависит от того, как быстро мы можем доставлять их конечному пользователю
Доставка
Цель
Предоставить пользователю свой продукт
Концепция
- Частота доставки обратно пропорциональна количеству багов. (DORA State of Devops report 2018)
- Как часто мы доставляем зависит от того, как часто конечный пользователь готов принимать новый релиз
Эксплуатация
Цель
Принципы
- Use platform to incapsulate changes
- Postmortem - отличная обратная связь о культуре
- commit messages
Мониторинг
Цель
Обнаружить и предупредить неожиданное поведение приложения
Концепция
Разделять по получателям.
Уведомления
Концепция
- Доставлять уведомления тем, кто может влиять на их причину.
- Спам уведомлений хуже чем их отсутствие.