---
title: Как правильно писать спецификацию
date: 2016-11-25T10:00
tags: [tests]
---

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

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

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

<!-- truncate -->

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

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

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

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

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

Работая без спецификации, разработчики постоянно будут сталкиваться с новыми, ранее неизвестными требованиями. Это создаёт угнетающую атмосферу отсутствия прогресса, шаткости всего решения, страха переписывания всего проекта из-за какой-то важной мелочи. Потратив день на продумывание спецификации, можно точней сделать оценку трудозатрат (estimation), сузить **[конус неопределённости](http://www.construx.com/Thought_Leadership/Books/The_Cone_of_Uncertainty/)** и снизить расходы

### Содержание

Спецификация касается только фич, а не задач типа _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 советует разбавлять спеку крупинками юмора, что-бы она не была слишком сухой и трудночитаемой

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

Некоторые спеки градируют приоритеты языком, [указывая](http://www.ietf.org/rfc/rfc2119.txt) какие фичи обязательны а какие не очень:

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

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

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

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

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

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

### Средства

Я визуал и предпочитаю изображения - [UML диаграммы](http://creately.com/blog/diagrams/uml-diagram-types-examples/), эскизы (balzamiq, axure), скриншоты со стрелками. Когда дело касается рутинных функций, без текста и списков не обойтись. ******Таблички****** полезны когда списки не работают - взаимозависимых данных становится много и они многомерны.

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

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

Автоматические тесты, да и мануальные формализованные тексты в [TestRail](http://www.gurock.com/testrail/), заготовки для UI тестов, наброски BDD — всё это тоже средства документации и проверки решения.

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

Для агрегации всей документации я в основном использовал [Confluence](https://ru.atlassian.com/software/confluence/pricing?tab=cloud), но можно посмотреть на MediaWiki или Google docs. Недостаток их всех в оторванности от кода и git-repo. Хранить документацию вместе с кодом лучше в формате markdown. Редакторы - [Mou](http://25.io/mou/), Atom, IntelliJ, Marked, Visual Studio Code.  

См также:

- [Painless Functional Specs](https://www.joelonsoftware.com/2000/10/02/painless-functional-specifications-part-1-why-bother/)
- [On Writing Product Specs](https://goberoi.com/on-writing-product-specs-5ca697b992fd#.iy5kdlu3j)
- [How to write a product vision](http://www.yegor256.com/2014/10/20/how-we-write-product-vision.html)
- [Specifying good requirements](http://www.jot.fm/issues/issue_2003_07/column7/)

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

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

О чём речь?

- Проблема и цели
- Stakeholders — заинтересованные пользователи. Кого это касается?

- Отделы компании — кого затронут изменения, кто что должен будет сделать в процессе
- Типы пользователей — visitor, user, client, admin

- Предположения (assumptions) — пользователи, доступность технологий, экономические факторы, развитие конкурентов, вероятное качество данных поставщиков
- Ограничения (constraints) — независящие от всех обстоятельства по времени, законодательству
- Scope — что по функционалу войдёт, а что нет
- Timeline/Lifecycle — что будет происходить после релиза, как будет меняться продукт/этот функционал впоследствии по времени

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

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

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

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

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

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

В больших компаниях, каждое требования выписывается в отдельную БД и получают **уникальный ID**, на который ссылаются UI-мокапы, код и тесты. Примерно как ticket ID в Jira. Инструменты — [SPEQit](https://www.speqit.com/), [Accompa](http://web.accompa.com/how-it-works/)

<iframe width="934" height="350" src="https://www.youtube.com/embed/NVfwoG5JgrA" title="Video 34 - Requirements Traceability" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
### 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-оптимизация

<iframe width="467" height="260" src="https://www.youtube.com/embed/ITS8sAkwRvQ" title="Video 14 - Nonfunctional Requirements" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

<iframe width="467" height="260" src="https://www.youtube.com/embed/Xkvt06WgzTk" title="Video 18 - Quality Attributes" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

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

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

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

<iframe width="467" height="260" src="https://www.youtube.com/embed/vs0UhQXc-VE" title="Video 11 - What is a Use Case" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

<iframe width="467" height="260" src="https://www.youtube.com/embed/HshfGCgWaE4" title="Video 13 - Use Cases and Functional Requirements" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

### 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 — [Swagger](http://swagger.io/), [Apiary](https://apiary.io/)
- Background-задачи (cron, MQ очереди)
- Код для повторного использования компонента
- Какое железо, серверы участвуют, какие компоненты на каких серверах живут  
    
- Какие шаги по релизу. Миграции БД, сервера. Как происходит откат неудачного релиза, бэкап  
    

См. также:

[Specification by Example: How Successful Teams Deliver the Right Software](https://www.amazon.com/gp/product/1617290084/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1617290084&linkCode=as2&tag=artjom-20&linkId=574cacd7e62dcf995056e6f9a75e5d95)

Gojko Adzic


<iframe width="934" height="350" src="https://www.youtube.com/embed/kv8XedJTEww" title="Visualise, document and explore your software architecture - Simon Brown" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

## Related

- [Kohana](/ru/blog/тестирование/unit-testirovanie-v-kohana-32/)
- [Protractor](/ru/blog/тестирование/protractor/)
- [Изолированное UI тестирование с Protractor](/ru/blog/тестирование/izolirovannoe-ui-testirovanie-s-protractor/)
