Как правильно писать спецификацию

Хождение по воде и разработка по спецификации легки, если и обе заморожены
Эдвард В. Берард

С самого начала моей карьеры, спецификация была больной темой. В маленькой веб-студии написание «спеки» сводилось в лучшем случае к двум-страничкам A4 с описанием нового модуля для уже работающей CMSки. Со временем я повидал и спеки как на 80 страниц от сторонних компаний в фиксированном pdf виде, так и в режиме постоянного scrumа где спека размазана по десяткам задачам в issue tracker’е.

Есть разница между спецификацией (SRS, техническим заданием), документацией и руководству по техническому обслуживанию, она в цели.

Цель спецификации зависит от фазы развития проекта:

  • объяснить всем цель, причины, ограничения, scope и ожидания
  • закрепить требования для этой фазы разработки
  • получить оценку по времени, сложности, доступности ресурсов
  • синхронизировать терминологию, поддерживать единую точку зрения для всех разработчиков
  • под конец реализации, спецификация превращается в документацию — в базу знаний, карту по продукту
  • автоматизировать тесты всех уровней
  • запустить в оборот дальнейшие документы -user guide, release notes, white paper, интерактивную помощь, статьи в блоге
  • подготовить tech manual для ремонта или интеграции системы

Scope — это треугольник ограничивающий ожидания всех сторон и напрямую влияющий на цену и деньги:

  • Функциональность (сумма всех фич)
  • Время выполнения
  • Качество и детальность проработки

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

Работая без спецификации, разработчики постоянно будут сталкиваться с новыми, ранее неизвестными требованиями. Это создаёт угнетающую атмосферу отсутствия прогресса, шаткости всего решения, страха переписывания всего проекта из-за какой-то важной мелочи. Потратив день на продумывание спецификации, можно точней сделать оценку трудозатрат (estimation), сузить конус неопределённости и снизить расходы

Содержание

Спецификация касается только фич, а не задач типа Improvement или Bug. Bug это несоответствие реализации и спеки. Improvement должен включать изменение спецификации на фазе release или code review.

Типы фич

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

  • UI компонент (frontend). Например popup, tooltip, модальное окно, календарь, autocomplete, slider картинок
  • Локальные бизнес-фичи (frontend + backend). Функционал свойственный именно этому продукту и завязанный на поведение пользователя. Например загрузка аватарок, изменение статьи, генерация excel-report’а.
  • Глобальные архитектурные фичи (frontend + backend). Например навигация, переводы, error pages, permissions, email notifications. Завязаны на бизнес-фичи и инфраструктуру.
  • Инфраструктурные, скрытые фичи (backend)​​. Например мониторинг, логи, транзактивность, масштабирование серверов, асинхронные очереди, API reference

Стиль и язык

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

  • Простота. Используйте минимум иностранных фраз, сленга и аббревиатур. Используйте односложные предложения.
  • Понятность. Выносите упоминания протоколов, кодировок, расширений в сноски или прячьте эти детали. Приводите пример расчётов
  • Неполнота. Требования не должна досконально описывать всё решение
  • Согласованность. Требования не должны противоречить друг другу
  • Точность и проверяемость. Избегайте:
    • обобщений (every, all, everywhere, never, any, each)
    • бесконечных глаголов (minimize, maximize, optimize, improve)
    • неточных глаголов (support, handle)
    • неточных прилагательных (easy, simple, efficient, flexible, user-friendly, superior, seamless, graceful)
    • неисчислимые (few, several, many, some)
    • «догадайся сам» (etc. и … , including but not limited to, where appropriate, if necessary, adequate, reasonable, sufficient, optionally)
    • латынь — etc., e.g., i.e., ergo
  • Однозначность.
    • Избегайте двусмысленных выражений (это, который) в сложносочинённых предложениях. Например, что значит «мама / папа «? Правильно — «мама, папа или оба».
    • Одна сущность — один термин, одна операция — один глагол. Минимум обобщений ( «Все варианты», «во всех местах», «Каку продукта Y» )

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

Joel Spolsky советует разбавлять спеку крупинками юмора, что-бы она не была слишком сухой и трудночитаемой

Уровни обязательности

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

  • MUST или MUST NOT, REQUIRED, SHALL — строго обязательный функционал
  • SHOULD или SHOULD NOT, RECOMMENDED — желательный функционал, но надо взвесить недостатки
  • MAY, OPTIONAL — реализуется по возможности

Причинно-следственная связь

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

Например — «Пользователь достаточным кредитом добавляет продукт в корзину и указывает количество. Зарезервированное количество продуктов на складе увеличивается».

Добавление и указывания количества — это разные операции или одна? А резервация продуктов связана с кредитом, или она для всех типов пользователей происходит?

Необходимо использовать разное время, либо более формально отделять precondition, user action, system reaction и post-condition.

Средства

Я визуал и предпочитаю изображения — UML диаграммы, эскизы (balzamiq, axure), скриншоты со стрелками. Когда дело касается рутинных функций, без текста и списков не обойтись. Таблички полезны когда списки не работают — взаимозависимых данных становится много и они многомерны.

Когда я пытался разобраться в существующих требованиях и существующем проекте, то очень помогал Mind Map, группируя и связывая задачи и требования, создавая точки фокуса. Готовое решение для повторно используемого UI-компонента часто хочется показать разработчикам. Без кода с подсветкой тоже никуда.

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

Автоматические тесты, да и мануальные формализованные тексты в TestRail, заготовки для UI тестов, наброски BDD — всё это тоже средства документации и проверки решения.

Автогенераторы документации и диаграмм полезны для создания документации по решению — mysql workbench, phpdoc, doxygen, jsduck. Это из разряда холиваров, когда стоит писать тесты — до кода или после него.

Для агрегации всей документации я в основном использовал Confluence, но можно посмотреть на MediaWiki или Google docs. Недостаток их всех в оторванности от кода и git-repo. Хранить документацию вместе с кодом лучше в формате markdown. Редакторы — Mou, Atom, IntelliJ, Marked, Visual Studio Code.

См также:

Наконец, вот шаблон для спеки. Оставьте только стоящие упоминания пункты!

1. Концепция / Обзор

О чём речь?

  • Проблема и цели
  • Stakeholders — заинтересованные пользователи. Кого это касается?
    • Отделы компании — кого затронут изменения, кто что должен будет сделать в процессе
    • Типы пользователей — visitor, user, client, admin
  • Предположения (assumptions) — пользователи, доступность технологий, экономические факторы, развитие конкурентов, вероятное качество данных поставщиков
  • Ограничения (constraints) — независящие от всех обстоятельства по времени, законодательству
  • Scope — что по функционалу войдёт, а что нет
  • Timeline/Lifecycle — что будет происходить после релиза, как будет меняться продукт/этот функционал впоследствии по времени

Скриншот самой важной области

2. Требования

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

Цели для каждой из заинтересованных групп.

  • Бизнес-требования. Что необходимо компании? Увеличить прибыль, ускорить рост, снизить риски
  • Пользовательские. Что необходимо конечному пользователю? Ускорение UI, облегчение действий, новые функции.
  • Технические. Что необходимо разработчикам? Поддержка кода, масштабируемость инфраструктуры, определение ошибок.

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

В больших компаниях, каждое требования выписывается в отдельную БД и получают уникальный ID, на который ссылаются UI-мокапы, код и тесты. Примерно как ticket ID в Jira. Инструменты — SPEQitAccompa

2.1 Нефункциональные требования

Каким мы хотим получить продукт?

Нефункциональные требования при работе продукта

  • Performance — максимальное количество одновременных пользователей, есть ли разница в зависимости от разных операций (read/write/delete), максимальная пропускная способность, время вычисления, время ответа и реакции, загрузка CPU, IO, памяти, max filesize
  • Reliability — как обрабатываются ошибки, перезапуск, дублируются ли данные, failsafe режимы, транзакции
  • Security — разграничение ролей пользователей, какая снижаются риски атак, как хранятся личные данные
  • Usability — ограничения по удобству, минимальное количество кликов при операциях, скорость обновления интерфейса, скорость загрузки страниц, количество элементов в формах или скорость заполнения среднестатистическим пользователем. Есть ли style guide
  • Configurability — где лежат настройки, централизованы ли они, используют ли какой-то сервис
  • Availability — сколько сервис максимально может быть в дауне
  • Durability — сколько надо хранить данные/логи после использования
  • Scalability — есть ли вертикальное/горизонтальное масштабирование сервиса или он фиксирован

Нефункциональные требования при создании

  • Reusability — можно ли повторно использовать, надо ли что-то при этом менять
  • Extensibility — можно ли расширить, добавив новые функции
  • Portability — можно ли запустить на других платформах
  • Interoperability — можно ли компонент использовать согласно открытому стандарту / протоколу
  • Supportability — простота в поддержке. Как легко понять логи, обнаружить ошибку, восстановить данные. Как предсказуемо поведение. Сколько стоит поддержка, какие требования по стилю и качеству кода, техническому долгу
  • Modularity — разделён ли функционал на части и почему. Как при этом происходит сборка и движутся данные
  • Testability — какие типы тестов должны быть и что покрывать, насколько код и архитектура должны быть тестируемыми
  • Localization — надо ли что-то переводить на другой язык, есть ли различие по странам, насколько сложные могут быть фразы, как легко можно добавлять переводы
  • Compatibility — совместимость с разными устройствами и браузерами. Надо ли поддерживать старые версии приложения
  • Legal — ограничения на использование лицензий, влияние на privacy policy, client agreement
  • Accessibility — надо ли поддерживать пользователей с ограничениями зрения. Hotkeys, поддержка разных устройств ввода, SEO-оптимизация

2.2 Функциональные требования

Что мы хотим получить в продукте?

  • Пользовательские сценарии / Use cases​ (краткий обзор, детальней в решении)
  • Для компонентов — размеры, события, анимация, позиционирование, связи с другими элементами (z-index)
  • Business rules — какие ограничения накладывает прикладная область, государственные регуляторы, международные стандарты, контракты

2.3 Риски и сложности

Что надо учитывать, какие взаимосвязи со всем проектом

  • Варьирующиеся и неопределённые внешние требования, сроки и требования по качеству
  • Внутренние требования (мониторинг, логи, транзакции)
  • Технические зависимости (легаси, тех. долг)
  • Неизвестность инструментов и технологий, предметной области
  • Человеческие зависимости
    • Человеческие отношения — доверие менеджмента комманде, комманды менеджменту (партизанинг), увольнения
    • Структура компании, межкоммандное взаимодействие, субподрядчики, партнёры
    • Внутриполитические дрязги, политика

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

Худшие последствия

Как сильно компания чувствительна к провалу этого проекта?

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

3. Техническое решение

Как это будет сделано? Преимущества и недостатки

Терминология

Единый словарь должен использоваться не только клиентом но и в css, в коде, в базе

Вид статических данных

Терминология плавно перетекает в связи между сущностями:

  1. Entity Relationship диаграмма включает связи сущностей (1:n, n:m).
  2. Нормальная схема БД. Включает, свойства и их типы, внешние ключи
  3. Class диаграмма — описывают какие классы в коде будут связаны с какими данными. Начинается описание поведения (методов)

Все эти диаграммы говорят о гибкости (насколько сущности разделены), понимаемости (названиях), тестопригодности (инкапсуляции) приложения

 

Вид пользователя

Пользовательские сценарии (use-case диаграмма) — пошаговое описание функций (роль пользователя, причина, действия, последствия)
Альтернативные сценарии (ошибки, валидация ввода). Что должно происходить с частично обработанными данными при ошибках?

Визуальный дизайн

Интерфейс и его взаимодействие с пользователем. Желательно связывать с конкретным use-case

  • Навигация (URL, меню, граф взаимосвязей видов)
  • Эскизы / наброски UI (mockup на доске, бумаге)
  • Визуальный дизайн интерфейса (PSD / HTML) — стиль, анимации, бренд, цвета, шрифты, вдохновение
  • Динамический дизайн / HMTL + JS. Очень полезен для frontend компонентов. Анимация, взаимодействие.

Вид динамических данных

Поток данных (data flow)​ — архитектурный обзор как данные кочуют между сервисами, что от чего зависит
Диаграмма взаимосвязей API

Взаимодействие (collaboration) — какие компоненты кого вызывают по каким методам
Последовательность (sequence) — в каком порядке идёт обмен данными между объектами во времени для конкретной операции
Конечный автомат (state machine) — в каких состояниях данные бывают

Вид сервера

  • Технологии и инструменты для сборки
  • Новые зависимости
    • Библиотеки и фреймворки
    • Репозитории
    • Использование внешних API
    • Отдача своего API вовне
  • Конфигурация
  • Серверы
  • Исключения, коды ошибок
  • Rest API — SwaggerApiary
  • Background-задачи (cron, MQ очереди)
  • Код для повторного использования компонента
  • Какое железо, серверы участвуют, какие компоненты на каких серверах живут
  • Какие шаги по релизу. Миграции БД, сервера. Как происходит откат неудачного релиза, бэкап