Мои лучшие практики

Что я считаю лучшими практиками и чего придерживаюсь.

Многое из нижеследующего вдохновлено 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

Мониторинг

Цель

Обнаружить и предупредить неожиданное поведение приложения

Концепция

Разделять по получателям.

Уведомления

Концепция

  • Доставлять уведомления тем, кто может влиять на их причину.
  • Спам уведомлений хуже чем их отсутствие.

Updated: