Пример написания функциональных требований к Enterprise-системе

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

Целью нашей разработки было создание с нуля учетной системы для одной из крупных российских компаний. Система была призвана заменить текущую, написанную в конце 90-х. В результате были реализованы платформа и один из бизнес-модулей. В реализованной части было порядка 120 объектов, 180 таблиц, около 30 печатных форм.

Хочу оговориться, что подход, описанный ниже, не универсален для написания любого ПО. Он подходит для систем уровня предприятия, которые строятся на основе объектно-ориентированного подхода: учетных, CRM-, ERP-систем, систем документооборота и т.п.

Вся документация на наш программный продукт состояла из следующих разделов:
  • Общая часть
    • Список терминов и определений
    • Описание бизнес-ролей
  • Требования
    • Бизнес-требования
    • Общие сценарии
    • Сценарии использования
    • Алгоритмы и проверки
    • Системные требования
    • Нефункциональные требования
    • Требования к интеграции
    • Требования к пользовательскому интерфейсу
  • Реализация
  • Тестирование
  • Руководства
  • Управление

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

Бизнес-требования описывали то, что необходимо бизнес-пользователям. Например, им вовсе не нужен объект системы Пользователь, но зато им нужно иметь возможность поменять стоимость товара в счете и распечатать его. Бизнес-требования состояли из общих сценариев, сценариев использования (use cases) и описания алгоритмов обработки данных. Подробно о разработке подобного рода требований можно узнать из книги Карла И. Вигерса и Джоя Битти Разработка требований к программному обеспечению.

Системные требования описывали свойства и методы всех объектов системы.

Нефункциональных требований в данной статье мы касаться не будем. Могу лишь отослать вас к отличной книге Architecting Enterprise Solutions авторов Paul Dyson, Andrew Longshaw.

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

Требования к пользовательскому интерфейсу – отдельная большая тема, возможно, для другой статьи.

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

Давайте рассмотрим подробнее, что такое список терминов и зачем он нужен.

Список терминов и определений


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

Поясню это на примере термина Пользователь. Википедия дает такое определение:

Пользователь — лицо или организация, которое использует действующую систему для выполнения конкретной функции.

Но нас оно не устраивало по нескольким причинам. Во-первых, в систему может зайти только человек, но не организация. Во-вторых, для нашей системы некорректно настоящее время глагола «использует» — система хранит данные о неактивных или удаленных пользователях, т.е. о тех, которые использовали систему ранее, но не могут в настоящее время. И наконец, у нас есть данные о потенциальных пользователях. Например, мы регистрируем сотрудника компании-клиента, который в дальнейшем может получить (а может и не получить) доступ в систему. Наше определение:

Пользователь — человек, который имеет, имел, или, возможно, будет иметь доступ в систему для совершения операций.
Теперь программист, прочитав определение, сразу поймет, почему свойство Логин в объекте Пользователь не обязательное.

Термины связаны друг с другом. В термине Пользователь используется «операция», поэтому приведу и ее определение:

Операция — совокупность действий, составляющих содержание одного акта бизнес-деятельности. Операция должна соответствовать требованиям ACID (Atomicity, Consistency, Isolation, Durability). Совокупность операций одного модуля представляет интерфейс взаимодействия клиент-сервер этого модуля.

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

Работа над списком терминов происходила постоянно. Мы поддерживали его полноту, т.е. старались, чтобы в документации не было термина, который бы не был определен в этом списке. Кроме того, были случаи, когда мы меняли термины. Например, по прошествии нескольких месяцев с начала написания требований мы решили заменить Контрагент на Компания. Причина была проста: оказалось, что никто не в состоянии в речи, при разговоре, использовать слово «контрагент». А если так, то он должен был быть заменен на что-то более благозвучное.

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

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

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

Описание бизнес-ролей


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

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

Пара примеров:


Уровни требований


Одной из важных концепций, которую мы применяли при разработке требований, было разделение их на уровни. Алистер Коберн в книге Современные методы описания функциональных требований к системам выделяет 5 уровней. Мы использовали 4 – три уровня бизнес-требований плюс системные требования:

Бизнес-требования
  1. Общие сценарии (соответствует уровню очень белого у Коберна)
  2. Сценарии использования (соответствует голубому)
  3. Алгоритмы и проверки (скорее черный)

4. Системные требования (нет прямого аналога, скорее черный)

Кроме того наши требования представляли из себя дерево (с циклами). Т.е. общие сценарии уточнялись сценариями использования, которые, в свою очередь, имели ссылки на проверки и алгоритмы. Поскольку мы использовали wiki, физическая реализация такой структуры не представляла проблем. Сценарии использования, алгоритмы и проверки использовали объекты, их свойства и методы, описанные на системном уровне.

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

На картинке ниже представлена часть нашей иерархии (о содержании речь пойдет дальше).

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

Интересен вопрос, кому в проектной команде какой из уровней нужен. Будущие пользователи могут читать общие сценарии. Но уже сценарии использования для них сложны, поэтому аналитик обычно обсуждает сценарии с пользователями, но не отдает их им для самостоятельного изучения. Программистам обычно нужны алгоритмы, проверки и системные требования. Вы однозначно можете уважать программиста, который читает сценарии использования. Тестировщикам (как и аналитикам) нужны все уровни требований, поскольку им приходится проверять систему на всех уровнях.

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

Бизнес-требования


Общие сценарии


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

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

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

Вот пример одного из общих сценариев:


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

Ссылка «Задание на печать», указывающая на описание объекта в системных требованиях, лишняя, поскольку никому не требуется перепрыгнуть на него из общего сценария. А вот ссылка «пакетная печать документов на груз» важна – она ведет на сценарий использования, формально описывающий действия пользователя и системы.

Наши сценарии использования имели следующий формат:
  • Заголовок со следующими полями:
    • статус (В работе | Готов к рецензированию | Согласован)
    • пользователи (по описанию бизнес-ролей)
    • цель
    • предусловия
    • гарантированный исход
    • успешный исход
    • ссылка на описание пользовательского интерфейса (разработанного проектировщиком интерфейсов)
    • ссылка на сценарий тестирования (заполнялось тестировщиками)
  • Основной сценарий
  • Расширения сценария

Сценарии использования


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

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


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

Алгоритмы и проверки


Интересная проблема возникла при написании алгоритмов. Аналитик пытался их описать как можно более полно, т.е. включать все возможные проверки и ответвления. Однако получившиеся тексты оказывались плохо читабельны, и, как правило, все равно какие-то детали упускались (вероятно, сказывалось отсутствие компилятора -). Поэтому аналитику стоит описывать алгоритм настолько полно, насколько это важно в плане бизнес-логики, второстепенные проверки программист сам обязан предусмотреть в коде.

Например, рассмотрим простой алгоритм ниже.


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

Системные требования


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

При разработке системы мы использовали объектно-ориентированный подход, а поскольку в основе ООП лежат понятия класса и объекта, то наши структуры данных – это описания классов. Термин «класс» специфичен для программирования, поэтому мы использовали «объект». Т.о. объект в требованиях равен классу в объектно-ориентированном языке программирования (в скобках замечу, что в паре разделов требований пришлось изгаляться, чтобы в тексте разделить объект-класс и объект-экземпляр этого класса).

Описание каждого объекта располагалось на одной wiki-странице и состояло из следующих частей:
  • Определение объекта (копия из списка терминов)
  • Описание свойств объекта
  • Описание операций и прав
  • Данные
  • Дополнительная информация

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

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

Название
Названием свойства оперирует как пользователь (например, «я изменил номер счета», Номер – свойство объекта Счет), так и проектная команда. Повсеместно в документации использовались ссылки на свойства в виде простой нотации Объект.Свойство, очевидной для любого участника проекта.

Тип
Мы использовали Datetime, Date, Time, GUID, String, Enum, Int, Money, BLOB, Array(), Float, Timezone, TimeSpan. Тип имел отражение на всех уровнях приложения: на уровне БД, сервера приложения, в пользовательском интерфейсе в виде кода и графического представления. Каждому типу было дано определение, чтобы их реализация не вызывала вопросов у программистов. Например, было дано такое определение типу Money: содержит вещественное число с точностью до 4-го знака после запятой, число может быть отрицательным и положительным; одновременно со значением система хранит валюту; валюта по умолчанию — российский рубль.

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

Признак наличия нуля
Да или Нет в зависимости от того, может ли поле не содержать значения. Например, поле типа Bool должно содержать одно из возможных значений, а поле типа String обычно может быть пустым (NULL). Это ограничение реализовывалось на уровне БД и на сервере приложения.

Признак уникальности
Да или Нет в зависимости от того, является ли это поле уникальным. Часто уникальность определяется на группе полей, в этом случае у всех полей в группе стояло Да+. Это ограничение реализовывалось на уровне БД (индекс) и на сервере приложения.

Комментарий
Описание поля: что означает, для чего нужно, как используется. Если значение свойства вычисляемое, то это указывается явно с описанием алгоритма расчета этого значения.

Кроме этих было еще две колонки, которые заполнялись программистами серверной части при реализации объекта:
  • Название свойства объекта в программном интерфейсе.
  • Название поля в БД.

Оба этих поля не обязательные, поскольку, например, свойство объекта может не храниться в БД, а быть вычисляемым, как сумма счета.

Хочу еще раз обратить внимание, что в написании требований принимали участие программисты. Это важно по многим причинам. Во-первых, таким образом программисты лучше осознавали требования, более того, требования становились «ближе к телу», а не просто неким куском бумаги, написанным каким-то аналитиком. Во-вторых, автоматически формировалась документация для API. В-третьих, поддерживалась трассируемость (traceability) требований, т.е. всегда было понятно, реализовано ли то или иное свойство, что особенно становилось важным при модификации требований. Безусловно, такая методология требовала большей дисциплины от программистов, что на самом деле являлось положительным фактором.

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

Как я уже писал, табличный вид очень удобен для расширения. Например, для описания начальной миграции у нас была колонка с именем свойства старой системы или алгоритмом преобразования данных. Также мы использовали специальные значки для описания того, как выглядит объект в пользовательском интерфейсе. Одно время у нас была колонка для имени индекса в БД, чтобы программисты не забывали их создавать для уникальных полей. При необходимости вы можете добавить колонку с размерностью типов данных для каждого свойства.

Вот типичное описание свойств нашего объекта.


Вторая таблица объекта содержала описание его операций и их прав. Каждая операция в системе имела уникальное название (колонка Операция), но в пользовательском интерфейсе (в меню) операции отображались под краткими названиями (Краткое название). Для выполнения любой операции надо было обладать определенным правом (Право). Колонка Комментарий для сложных методов содержала описание алгоритма или ссылку на него или на более общий сценарий использования. CRUD операции над всеми типами объектами у нас были стандартизированы, поэтому для них алгоритмы обычно не требовались.

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


В этом разделе были также таблицы, описывающие переход по статусам.


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

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

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

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

Многие скажут, что такая детализация требований отнимает много времени и не нужна. На что я возражу – а как программист догадается, что конкретно необходимо реализовать? Разве фразы «Необходимо реализовать объект Пользователь» достаточно, чтобы через некоторое время получить работающий код? Сколько надо выпить чая с аналитиком, чтобы вытащить из него данные по 40 (столько было у нас) свойствам пользователя? Кто, как не аналитик или проектировщик, должен приложить усилия и описать все объекты?

Постановка задач программистам


После описания того, как выглядят требования, рассмотрим интересный вопрос: как должны быть сформулированы задачи для программистов (ограничимся серверной частью многозвенного приложения)? Оказывается, большинство задач (не дефектов) сводится к трем вариантам:

Типовая задача 1
Заголовок: Реализовать такой-то объект.
Текст задачи — ссылка на страницу с системными требованиями к объекту.
В такой задаче программисту необходимо:
  • создать структуры в БД (таблица, ключи, индексы, триггеры и т.д.);
  • реализовать доменный объект;
  • реализовать создание начальных данных.
Все это возможно сделать на основе описания объекта в системной части требований. Программист также должен дополнить таблицу с описанием свойств названиями полей таблицы БД и объекта API.

Типовая задача 2
Заголовок: Реализовать такую-то операцию такого-то объекта и права на нее
Текст задачи — ссылка на страницу с системными требованиями к объекту.
Программист находит на странице название операции и права, а по ссылке в колонке Комментарий – алгоритмы, проверки, сценарий использования.

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

Инструмент для написания и управления требованиями


Как, возможно, многие догадались, для работы с требованиями мы использовали Atlassian Confluence. Хочу кратко перечислить достоинства этого продукта.
  • Удаленная работа. Собственно, как и у любой wiki.
  • Ссылки. Как вы видели выше, ссылки для нас – один из основных инструментов для связывания отдельных частей требований.
  • Возможность дробить требования на части (каждая часть – на своей странице).
  • Оповещения при изменении. Это одно из важнейших средств совместной работы. Например, получив такое оповещение по одному из сценариев, руководитель разработки может ставить задачи разработчикам, а тестировщики знает, что надо скорректировать сценарии тестирования.
  • Комментарии. Многие страницы требований у нас обрастали развесистыми иерархиями комментариев. В Confluence работать с ними достаточно удобно, поскольку иерархия не плоская, а в виде дерева. Кроме того есть возможность использовать полноценный редактор, а не просто текст.
  • Наличие мощного текстового редактора. Не буду здесь подробно останавливаться, отмечу лишь, что на всем протяжении нашей работы Atlassian совершенствовал редактор, и если вначале было достаточно много глюков, то затем подавляющее большинство из них было исправлено.
  • Хранение истории, сравнение разных версий страниц, возможность отката на старую версию.
  • Просмотр иерархии страниц в виде дерева.

Однако было и несколько проблем:
  • Поскольку все требования используют одни и те же названия объектов и их свойств, то было бы очень удобно иметь инструмент, который при изменении названия менял его во всей документации. А при удалении – находил все, уже недействительные, ссылки на него.
  • Не было возможности сбора статистики. Например, каждое требование имело статус, но мы не могли автоматически собирать статусы всех требований и иметь динамическую картину процесса разработки требований. Но, кажется, на данный момент что-то подобное в Confluence уже появилось.
  • Диаграммы приходилось рисовать в другой системе, сохранять в PNG и уже картинку помещать на страницу Confluence. При этом еще надо было приложить исходник, чтобы через пару месяцев его можно было найти и поправить.
  • Я не нашел способа экспортировать иерархию страниц в MS Word. Экспорт в XML и PDF очень часто глючил (возможно, дело в размере иерархии).


В конце хочу выразить благодарность Вадиму Лободе и Артему Каратееву за ценные советы и тщательное рецензирование данной статьи.

Антон Стасевич
Метки:
Поделиться публикацией
Комментарии 36
  • +2
    «Поэтому аналитику стоит описывать алгоритм настолько полно, насколько это важно в плане бизнес-логики, второстепенные проверки программист сам обязан предусмотреть в коде. [...] В алгоритме указана всего одна проверка, но очевидно, что при написании кода метода программист должен реализовать проверки на входные параметры; выбросить исключение, если текущий пользователь не определен и т.д. „

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

    Собственно, меня в этом подходе смущает “программист _обязан_». У нас в таких случаях четко предупреждают «поведение системы в случаях, не описанных в требованиях, _не определено_».
    • 0
      Например, почему если пользователь не определен, должно быть исключение, а не сообщение об ошибке с перенаправлением на механизм входа в систему?

      Я согласен, что тут возможны варианты. Обычно это определяется архитектурой приложения. Это всего лишь пример.
      “программист _обязан_». У нас в таких случаях четко предупреждают «поведение системы в случаях, не описанных в требованиях, _не определено_».

      Из того, что оно не определено (в требованиях), не следует, что программист его не должен учесть. А он должен. Надеюсь, не будем отрицать необходимость проверок на корректность входных параметров -)?
      • +3
        >> Из того, что оно не определено (в требованиях), не следует, что программист его не должен учесть.
        Под «не определено» подразумевается «любое поведение системы, которое последует — корректно».

        >> Надеюсь, не будем отрицать необходимость проверок на корректность входных параметров -)?
        Будем. Вы путаете правила хорошего тона программиста с требованиями. Понятие «корректность входных параметров» — очень широкое. Например, надо ли проверять, что цена не отрицательная? А что она не ноль? Вот и с null-значениями то же самое — _правила хорошего тона_ рекомендуют проверить, что обязательное значение присутствует, как можно раньше и явно, чтобы было легче отлаживать систему, но для пользователя разницы нет: и так, и так будет техническая ошибка — до тех пор, пока это правило не будет вынесено в бизнес и не описано явно.

        Самая страшная вещь в требованиях — это умолчания.
        • +1
          Будем.

          Зря. При делении на 0 система накроется, а могла бы выдать человеческую ошибку.
          Вы путаете правила хорошего тона программиста с требованиями.

          Я не путаю. Я говорю о том, что невозможно все отразить в требованиях (или это потребует неадекватно больших трудозатрат аналитика). Аналитик решает, что важно (например, может решть, что — из вашего примера — проверка на неотрицательную цену — очень важна), а что не важно. И важные проверки описывает.
          Но у программиста — помимо требований от аналитика — есть еще и опыт, и требования по архитектуре (от архитектора / ведущего разработчика / менеджера проекта).
          … _правила хорошего тона_… чтобы было легче отлаживать систему

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

          Есть — и очень большая: получить сообщение runtime на английском или user-fiendly с описанием того, что происходит в ему понятных бизнес-терминах.
          • +5
            >> При делении на 0 система накроется, а могла бы выдать человеческую ошибку.
            И тут мы немедленно упираемся в вопрос «что такое человеческая ошибка».

            >> И важные проверки описывает.
            Именно. Вы же сами решаете, что остальные фрагменты поведения системы _не важны_, иначе бы их определил аналитик. Вот система себя и ведет, как придется.

            >> И дело не в отладке, а в том, что (1) система не должна падать и (2) пользователю надо выдать корректную ошибку.
            Утверждение «система не должна падать» (а) недостижимо и (б) противоречит принципу fail early. Я искренне убежден в том, что столкнувшись с непредусмотренной ситуацией система должна упасть, чтобы не усугублять положение.

            >> Есть — и очень большая: получить сообщение runtime на английском или user-fiendly с описанием того, что происходит в ему понятных бизнес-терминах.
            Чтобы получить описание в понятных бизнес-терминах, ошибка должна быть описана в бизнес-терминах. Бизнес-терминологией владеет аналитик — вернулись к началу.

            Понимаете ли, для пользователя сообщение «Текущий пользователь не определен» ничем не лучше «NullReferenceException» — он в обоих случаях не знает, что делать дальше.
          • +1
            кстати, в некоторых случаях — 0 также вполне корректная цифра выражения стоимости, например, в финансовых системах. Столкнулись с таким, когда добавил в чат проверку на пустое сообщение вида empty() — а там 0 не пропускает, хотя на вопрос о стоимости актива ответ 0 часто полностью корректен (как и отрицательные числа также)
            • 0
              Именно поэтому я и привел этот пример.
      • +1
        Вот система себя и ведет, как придется.

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

        Вы смотрите на систему с т.з. отладки, а не использования ее в реальных условиях (для чего она предназначена). Для систем класса предприятия (о них речь в статье) падение — тяжкий грех. Из того, что это недостижимо не следует, что не надо к этому стремиться.
        Бизнес-терминологией владеет аналитик — вернулись к началу.

        Вовсе нет. Я как раз писал, что бизнес-терминологией должен владеть и программист и тестировщик.
        «Текущий пользователь не определен» ничем не лучше «NullReferenceException» — он в обоих случаях не знает, что делать дальше.

        С т.з. программиста — да, все равно. Но с т.з. пользователя — нет. Даже ели брать такой экстремальный пример — то «тон делает музыку». С кем вам приятнее разговаривать: с тем, кто орет без повода, пусть даже говорит умные вещи, или с тем, кто разговаривает спокойно? Помните классический пример про коды ошибок в IBM (когда надо было лезть в мануал, чтобы найти описание ошибки, чей код показался на экране)?
        Также я говорю об общих принципах — в 80% случаях ошибки можно сформулировать в бизнес-терминах. Еще 10% пользователь скорее всего не увидит никогда (они не возникнут — проверки не сработают — как раз случай с отсутствием текущего пользователя), еще 10% — надо стараться сформулировать по-человечески.

        Еще раз: программист — не просто кодер — он участник команды по созданию системы. Ему нужны требования — ок, аналитик их дает. Но и программист должен думать, как лучше сделать для пользователя. В каких-то случаях нужно что-то уточнять у аналитика, в каких-то — полагаться на разработанные архитектурные и т.п. принципы, в каких-то — додумывать самому.
        • –1
          >> Но если ему не все равно — то он участвует в формировании поведения системы — удобного для пользователя.
          Программист не знает, как удобно пользователю. Откуда?

          >> Для систем класса предприятия (о них речь в статье) падение — тяжкий грех.
          Нет. Для системы класса предприятия тяжкий грех — это потеря данных и отказ в обслуживании. А падение, которое не влияет на остальные операции — не грех, а нормальная, регулярно встречающаяся ситуация.

          >> Но и программист должен думать, как лучше сделать для пользователя.
          Это немножко не входит в круг его навыков (если входит — то он уже не [только] программист). Поэтому в его суждениях по этому поводу могут быть ошибки, и они, что самое важное, ненаказуемы. Вы хотите, чтобы программист брал на себя часть аналитической работы. Само по себе это не вполне допустимо, только вы должны понимать, что в этот момент вы просите человека выполнять две конфликтующих обязанности. Результат будет соответствующим.

          И да, то, о чем вы говорите, описывается банальным требованием «все ошибки, достигающие пользователя, должны быть сформулированы по-русски». После этого умолчание из требований исчезает, а ожидаемое поведение становится очевидным.
          • –1
            Извините, задумался в процессе предложения. «Само по себе это вполне допустимо» («не» — лишнее).
          • +1
            Программист не знает, как удобно пользователю. Откуда?

            Это лукавство, желание уйти в свой мирок кодирования и отвечать лишь за применение шаблонов. Программист разве сам не пользуется ПО? О, сколько раз я слышал, что что-то в ReSharper сделано не так -). Ну, а кроме того, общие принципы работы разрабатываемой системы разве не всей командой обсуждаются?
            А падение, которое не влияет на остальные операции

            Ну, тут просто у нас терминология не совпала. Я, как программист С++, считаю, что падение = отказ в обслуживании. Для вас (наверно, Java/C#) падение — это исключение, попавшееся на глаза пользователю.
            в его суждениях по этому поводу могут быть ошибки, и они, что самое важное, ненаказуемы

            Я никого не хочу наказывать. Я пытаюсь объяснить, что ПО делается всей командой. И нет идеальной ситуации, когда аналитик описал на словах целиком алгоритм, а программисту надо только перевести его на язык программирования. И, кстати, хорошо, что такой ситуации нет (поскольку возникает синергия).
            А разве в рамках вашей парадигмы не конфликтует написание unit-тестов с реализацией методов?
            В рамках моей — нет, поскольку программист — не кодировщик, а «человек думающий» -), т.е. понимает то, что кодирует с т.з. бизнеса.
            «все ошибки, достигающие пользователя, должны быть сформулированы по-русски»

            Не, это упрощение. Я не о языке (кто сказал, что мы только для России пишем? -) — я о бизнес-смысле, заложенном в сообщении об ошибке (см выше — где я писал о 80-10-10).
            • 0
              >> Это лукавство, желание уйти в свой мирок кодирования и отвечать лишь за применение шаблонов. Программист разве сам не пользуется ПО?
              Пользуется. Но ПО, которое удобно программисту, далеко не всегда удобно бизнес-пользователю. В обратную сторону, кстати, тоже работает.

              >> Ну, а кроме того, общие принципы работы разрабатываемой системы разве не всей командой обсуждаются?
              Далеко не обязательно. И уж до программистов (которые исполнители) тем более редко доходит.

              >> Я, как программист С++, считаю, что падение = отказ в обслуживании. Для вас (наверно, Java/C#) падение — это исключение, попавшееся на глаза пользователю.
              Для меня падение — это когда система (или ее конкретный модуль) была полностью остановлена и перезапущена начисто.

              >> Я пытаюсь объяснить, что ПО делается всей командой.
              ПО действительно делается всей командой. Просто важно понимать цели каждого члена этой команды.

              >> А разве в рамках вашей парадигмы не конфликтует написание unit-тестов с реализацией методов?
              Нет, не конфликтует. А вот функциональное тестирование с разработкой — уже конфликтуют.

              >> программист — не кодировщик, а «человек думающий» -), т.е. понимает то, что кодирует с т.з. бизнеса.
              Зачем тогда вобще нужны аналитики?

              >> Не, это упрощение. Я не о языке (кто сказал, что мы только для России пишем? -) — я о бизнес-смысле, заложенном в сообщении об ошибке (см выше — где я писал о 80-10-10).
              Значит, переформулируйте требование. Важно, чтобы оно было явно озвучено.
              • +1
                И уж до программистов (которые исполнители) тем более редко доходит.

                По-моему у нас именно в этом месте основное противоречие -). При написании ПО возможны разные парадигмы. Я придерживаюсь той, кот говорит, что программист — не простой кодировщик. Кроме того мой опыт показывает, что лучшие программисты — это не простые кодировщики. Но, если верно обратное (программист=кодировщик) — то соглашусь, что на плечи аналитика ложатся и задачи описания низкоуровневых проверок (с чем он, скорее всего, не справится).
                Значит, переформулируйте требование. Важно, чтобы оно было явно озвучено.

                Требование очень простое — ошибка должна быть сформулирована в бизнес-понятиях и быть понятна пользователю. У нас, кстати, это было записано.

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

                  С одной стороны, у вас может работать Петя. Петя ничего не понимает в бизнес-поцессах заказчика, зато умеет решать алгоритмические задачи со множеством параметров и мысль «объектами». В таком случае, вашему аналитику придется донести до Пети все возможные низкоуровневые проверки, поскольку значение цены null для Пети катастрофой не является.

                  С другой стороны, в команде может быть Вася. В отличие от Пети, Вася представяет себе как рабоает бизнес заказчика и может хотя бы примерно изобразить если не IDEF-диаграмму процессов, то хотя бы их блок-схемы в Visio. Васе уже не нужен полный перечень низкоуровневых проверок, Вася о них в курсе или докагывается, где они могут быть нужны — если что, спросит.

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

                  Аналогично с падениями системы и прочими нюансами: нельзя просто ждать, что программист по-умолчанию понимает что нужно заказчику.

                  Отчати эта разница — именно то, что оправдывает использование ГОСТ 34 в качестве методологии при разработке масштабных ИС: ГОСТ (в случае прямого следования ему) обязывает архитектора системы и аналитика четко обозначать максимальное количество низкоуровневых проверок и деталей. Таким образом Петя получает полныц набор информации, а Вася может прочитать часть документации «наискосок» и ему этого будет достаточно.
                  • 0
                    обязывает архитектора системы и аналитика

                    Согласен. Я во втором комментарии писал, что "… у программиста — помимо требований от аналитика — есть еще и опыт, и требования по архитектуре (от архитектора / ведущего разработчика / менеджера проекта)."
                    • 0
                      Кстати, похоже, что на вашем проекте Петя не нужен — ведь аналитик все алгоритмы уже описал. -) Я исхожу из того, что уж если аналитик должен описать все низкоуровневые проверки, то алгоритмы-то уж он точно должен описать.

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

                        а вы не задумывались что на ПК и на часах android будут совершенно разные алгоритмы? Например при работе с графикой.

                        Я о том, что есть ограничение ресурсов. На ПК вам доступно 90Гбайт оперативки, а на часах всего 8Мбайт. А станок ЧПУ ест не более 200Кбайт.
                        Ваш аналитик будет описывать все алгоритмы под всё железо в мире?
                        • 0
                          и на часах android

                          Могу только процитировать статью: «Хочу оговориться, что подход, описанный ниже, не универсален для написания любого ПО. Он подходит для систем уровня предприятия, которые строятся на основе объектно-ориентированного подхода: учетных, CRM-, ERP-систем, систем документооборота и т.п.»

                          Если отвечать конкретно, то в жизни, конечно, все возможно, но скорее всего реализация «того же самого» на часах потребует изменений на системном уровне приложения, а не в алгоритме обработки бизнес-данных. Вот на системном Петя и будет активно работать.
                          • 0
                            т.е. под алгоритмами вы подразумеваете только обработку бизнес-данных и ни каких других алгоритмов?
                            Например валидация номеров телефонов на чьи плечи падает?

                            Не хочу общими фразами задавать вопросы, будем по конкретике.

                            +380… или 810380...? Тут уже не совсем бизнес логика, это вопросы совместимости оборудования к которому будет привязана ваша CRM. Стоит это описывать в Аналитике или программист по умолчанию сам догадается (и должен ли программист знать ГОСТ по зональности номеров телефонов?)
                            Или возьмем международный стандарт, но аналоговые линии при принятии на вход "+" просто выдадут исключение (старое оборудование и т.д.)
                            • 0
                              это вопросы совместимости оборудования к которому будет привязана ваша CRM

                              Это про интеграцию (отдельные требования). Да, аналитик должен предусмотреть, что номер телефона должен в разные системы передаваться в разных форматах.
                    • 0
                      >> Я придерживаюсь той, кот говорит, что программист — не простой кодировщик. Кроме того мой опыт показывает, что лучшие программисты — это не простые кодировщики.
                      У нас с вами противоречие в том, как понимать термин «простой кодировщик». Я вот считаю, что чтобы выйти за уровень «простого кодировщика», нужно начать принимать технические решения. А вы — что нужно начать принимать бизнес-решения.

                      >> на плечи аналитика ложатся и задачи описания низкоуровневых проверок
                      Вы считаете, что поведение системы для определенного и неопределенного текущего пользователя — это низкоуровневая проверка?

                      >> Требование очень простое — ошибка должна быть сформулирована в бизнес-понятиях и быть понятна пользователю. У нас, кстати, это было записано.
                      Вот с момента, как оно записано, у меня больше нет вопросов. Я против _неявных_ требований.

                      И да, для меня признак хорошего программиста — это то, что как только он видит потенциальное неописанное требование — например, поведение системы при ошибке — он не игнорирует его, и не делает тихо, как считает лучше, а идет к постановщику задачи.
                      • 0
                        А вы — что нужно начать принимать бизнес-решения.

                        Проверка на входные параметры — это не бизнес-решение. Например, пришел тебе указатель на объект — проверь его на NULL.
                        Вы считаете, что поведение системы для определенного и неопределенного текущего пользователя — это низкоуровневая проверка?

                        В статье в приведенном алгоритме сказано, что ЗнП.Пользователь надо установить в текущего пользователя. Если текущего пользователя нет, то произошла какая-то системная ошибка. И да, программист должен провести проверку и выбросить наверх ошибку, если текущий пользователь = NULL. Иначе нельзя сказать, что алгоритм реализован верно. Ведь суть этого алгоритма (поднимаемся на уровень выше) не только в том, чтобы поменять статус ЗнП, но и указать, кто конкретно взял его в работу.
                        Я против _неявных_ требований.

                        С этим я согласен. Я лишь делаю упор на то, что лучше аналитику облегчить жизнь и оставить ему описание бизнес-требований. А то, что касается, например, таких вещей, как: какие сообщения выдавать, как проверять входные параметры, как комментировать код, — то можно и без него обойтись. У нас это было в разделе Реализации при описании программных подсистем.
                        он не игнорирует его, и не делает тихо, как считает лучше, а идет к постановщику задачи.

                        Это хорошо. Я не против (а часто и за -). Я обращаю внимание вот на что: если постановщик описал все без исключения детали алгоритма, то что остается программисту? Все лишь перевести алгоритм на язык программирования. Вот это я и называю простым кодировщиком.

                        И, возвращаясь к началу: «А вы — что нужно начать принимать бизнес-решения.» — верно. Понятно, что бизнес-решения бизнес-решениям рознь. Но программист должен думать не только о том, как лучше закодировать алгоритм от постановщика, но и как это все отразится на пользователе. Программист не должен думать только о красоте внутренней архитектуры системы, но и о том, как она отвечает требованиям/ожиданиям пользователя.

                        Вот пример (происходило буквально два дня назад): одна и та же проверка в коде не проходит по двум совершенно разным причинам с т.з. пользователя. Т.е. проверка так низко в коде, что там непонятно, удаляет пользователь объект или его редактирует. Есть два выхода: (1) оставить прекрасную архитектуру, но выдать трехэтажное сообщение пользователю (кот его может повергнуть в шок и трепет), или (2) доработать код так, чтобы в месте проверки можно было понять, что делал пользователь, и выдать два разных простых сообщения.

                        И таких вещей возникает масса. Могу лишь повторить, что «мой опыт показывает, что лучшие программисты — это не простые кодировщики». Еще раз — я пишу о системах ERP/СRM/DMS, не касаюсь, например, встроенных систем.

                        Уважаемый @crackpotcrackpot выше привел неплохой пример про Петю и Васю. Петя — ваш «непростой кодировщик», принимающий технические решения, а Вася — мой «непростой кодировщик», принимающий бизнес-решения. А теперь задумаемся вот над чем: какое отношение Петь и Вась надо при разработке ERP? 1 к 5? Ведь системная архитектура занимает значительно меньший объем, чем бизнес-алгоритмы.

                        Второй положительный эффект от Вась — это синергия. Грубо, постановщик-то тоже может ошибаться, делать что-то не лучшим образом. Безусловно, можно и нужно дать на review алгоритм другому постановщику. Но почему программист (или тестировщик) не может предложить лучшее решение? Часто так и происходит — программисту лучше виден нижний уровень системы — и от него идет подсказка аналитику.
                        • 0
                          >> Например, пришел тебе указатель на объект — проверь его на NULL.
                          А эти проверки я и не прошу описывать. Но вот что делать, если пришло незаполненное поле? Оно должно быть заполнено? Если где-то написано, что оно обязательное — то да. А если нигде не написано?

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

                          >> Я обращаю внимание вот на что: если постановщик описал все без исключения детали алгоритма, то что остается программисту? Все лишь перевести алгоритм на язык программирования.
                          Вы так пишете, как будто это легко.

                          Во-первых, когда в алгоритме написано "… и сохраняет в базу данных", за этим может быть неделя-другая разработки. Но это еще мелочи.

                          А во-вторых… требования не ограничиваются алгоритмами. Вот есть задача: сынтегрировать системы А и Б, система А — потребитель данных, система Б — поставщик. В требованиях от аналитика написано «данные нужно получать из системы Б, ограничения по набору данных такие-то, запаздывание данных в штатном режиме не должно превышать суток, в случае превышения этого параметра необходимо информировать...». Это, с моей точки зрения, достаточные требования (само преобразование данных мы сейчас не рассматриваем). Но алгоритм за ним может быть как простой, так и сложный.

                          >> Т.е. проверка так низко в коде, что там непонятно, удаляет пользователь объект или его редактирует. Есть два выхода: (1) оставить прекрасную архитектуру, но выдать трехэтажное сообщение пользователю (кот его может повергнуть в шок и трепет), или (2) доработать код так, чтобы в месте проверки можно было понять, что делал пользователь, и выдать два разных простых сообщения.
                          Забыли третий выход, правильный: сделать первичную проверку на том уровне, где действие пользователя очевидно, и дополнительную (защитную) — на нижнем уровне.

                          >> Но почему программист (или тестировщик) не может предложить лучшее решение?
                          Предложить — может. Он не может его самостоятельно принять.
                          • 0
                            Уважаемый, lair. Я могу ответить, но ответы мои будут всего лишь повторять то, что я уже писал выше. По-большому счету я не вижу больших различий в наших позициях (тем более, раз уж вы признали, что какие-то проверки можно не описывать -). Возможно, отличие в том, что я культивирую в программистах ориентацию на бизнес, а вы — на системную архитектуру. В любом случае — удачи в ваших проектах!
                            • 0
                              Я культивирую в «своих» программистах не ориентацию на системную архитектуру, а умение понимать, какое решение является техническим, а какое — бизнесовым.
            • 0
              Требования к интеграции описывали низкоуровневый интерфейс взаимодействия новой системы с несколькими другими системами компании. Здесь мы их рассматривать не будем.


              А ведь это самое интересное и сложное.

              Любой программист может построить дом рядом с другим домом, но далеко не любой сможет достроить этаж в уже существующем.
              • 0
                Не соглашусь что интересное, но то что сложное и местами мозговыносящее — это точно
                • 0
                  Имею в виду интересное с точки зрения менеджмента :)
                  • 0
                    Главное в управлении тут — создать тестовую среду более-менее похожую на production. Если не выходит — приходится думать о всяких tricks. Выдумывать приходится также, как давать нагрузку на тестовую среду.
                  • 0
                    100% согласен. Интеграция — одна из самых сложный частей в разработке. У нас ее было много разной: и синхронной и асинхронной. Все в одну статью не впихнуть. Тем более, мне кажется, что там интересны именно технологические решения, а не методология описания требований. А технологии пусть программисты, кот непосредственно их реализовывали, описывают.
                    • 0
                      Да, особенно со старыми система и базами данных(вроде Sybase).
                      Хотя и с новыми система вроде последних версий SAP — не легче.
                • 0
                  Странно, что в вашей документации не было ничего про архитектуру и проектирование.

                  Видимо, дело в том, что вы залезли в чёрный ящик с «системными» требованиями.

                  Называние требований «системными» очень неудачно, т.к. система — это не только софт, а и остальные немаловажные компоненты — железо, процессы, люди, правила.

                  Смотрите уровни требований и документов требований по ISO 29148 (если не нравится ГОСТ 34).
                  • 0
                    Странно, что в вашей документации не было ничего про архитектуру и проектирование.

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

                    В действительности этот раздел назывался ТЗ. Но в статье не хотел дразнить любителей ГОСТов -).
                    Предлагайте свое название!
                  • 0
                    Спасибо за термин «сценарий»! Я давно предлагаю термин «описание бизнес-процесса» заменить на короткое «сценарий».
                    • 0
                      Спасибо! Отличная статья.

                      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.