В данной статье рассматривается ситуация, типичная для проектов, в которых странным образом возникают одни и те же ошибки. И никто не понимает как так получается. Или делает вид, что не понимает... Если ты владелец IT-продукта и болеешь за свое дело, то без качественных технических заданий не обойтись. В больших нетиповых проектах постановка и формирование ТЗ становится нетривиальной. Нужно описать много условий, ветвлений и прочих сложных логических конструкций, которые «с наскоку» не реализовать, ведь на бумаге это выглядит лишь как набор абстракций. А так уж устроен наш мозг, что ему нужна конкретика и образы, а не полотна с текстом! Взять, например, разработку фриланс-портала. У проекта обычно несколько статусов. Всякий статус доступен для пользователей с разными ролями, у каждой роли есть набор атрибутов и свойств, характерных только для этого статуса и этой роли. А еще есть дополнительные, вроде бы, автономные сущности такие как «Переписка», «Оплата», «Отзывы». Они вроде бы самостоятельные, но, так или иначе, перекликаются со статусами и ролями. Все это при пересечении дает очень большой набор вариантов, который нужно запрограммировать. Возникает вопрос, как подать информацию специалисту, чтобы она была действительно понятна и непротиворечива, и, желательно, наглядна? Есть всего два возможных базовых варианта. Остальное - их комбинации. Вариант 1. Подумать и сформулировать набор правил для каждой сущности. Например, берем сущность «Переписка» и формулируем правила по ее доступности. Это может выглядеть следующим образом:  Если между специалистом и заказчиком была переписка, то она блокируется при следующих условиях: a.      Проект получает статус «Заблокирован» b.      Проект получает признак «Снят с публикации» c.       Проект получает статус «Закрыт» (полное закрытие) d.      Специалист отказался от выполнения проекта на этапе поиска исполнителя На данном этапе важно, чтобы правилом покрывались все возможные варианты событий. Если этого не произойдет, а программист не подумает самостоятельно (или не задаст вам вопросы), то вы можете получить достаточно неприятные сюрпризы на этапе приемки проекта.  Кстати, как вы думаете, какой сюрприз (явно ненужный нам) можно получить по этому правилу? Напишите в комментариях, если заметите! Когда вы формулируете такие правила важно донести до специалистов необходимость в их критичном восприятии! Если на этапе реализации они смогут увидеть несовершенства в формулировках, то должны дать вам немедленную обратную связь, чтобы уточнить правило. Лайфхак: это лучше зафиксировать в проектной документации в качестве принципа работы! Таким образом, ваше ТЗ будет состоять из описаний наборов правил, реализовав которые вы должны получить красиво-работающий продукт. Но что, если вы не смогли чего-то учесть? Тут на помощь приходит второй вариант постановки задачи… Вариант 2. Рассмотреть все частные случаи разрабатываемого процесса, разложив его на максимально подробные составляющие. Здесь проблема состоит в том, что процесс в сложных системах может быть настолько большим, что представить его полным набором мелких составляющих, мягко говоря, затруднительно. А, порой, и вовсе невозможно.  Вот вам абстрактный пример. У нас есть: 3 состояния проекта S = (S1, S2, S3) 3 роли R = (R1, R2, R3)  и три атрибута А = (А1, А2, А3), которые зависят от того, как пересекаются S и R.  По каким-то причинам нам трудно сформулировать общие правила, по которым мы должны запрограммировать систему. Поэтому мы просто должны описать все возможные пересечения этих комбинаций.  Например, мы подумали, и у нас получилось так:  S1 + R1 = А1 S1 + R2 = А2 S1 + R3 = А3 S2 + R1 = А1 S2 + R2 = А2 S2 + R3 = А3 S3 + R1 = А1 S3 + R2 = А2 S3 + R3 = А3  Таким образом, пересечение двух небольших множеств, состоящих всего из трех объектов дало нам выборку из 9 вариантов!  А если множество статусов S получит еще статус S4? Сколько будет вариантов? Уже 12! А если размеры обоих множеств станут равны 4-м? Тогда вариантов будет 16! Это я еще не привел пример, когда нам нужно пересечь 3 множества или больше! К чему это я? К тому, что очень легко при таком подходе запутаться. А уж как сильно демотивируют программистов такие простыни описаний и как сильно взлетает стоимость проектов от этого – я скромно умалчиваю. Мы рассмотрели два способа подачи информации для ТЗ в сложных проектах. Я считаю, что у обоих способов есть свои преимущества и недостатки. Способ постановки задачи обобщенными правилами приближен к тому, как закладывают логику в свои решения программисты, но требует от нас предварительно проделать достаточно большой объем аналитической работы. Если эта работа проделана должным образом, то второй способ может и не понадобится. Кстати, бывают случаи, когда правило видоизменяется по ходу проекта, например, если мы что-то не учли изначально или в проекте появляются новые вводные. Такое бывает по невнимательности или по Agile:) Способ описания частных случаев считаю целесообразным тогда, когда у нас не получилось сформулировать однозначный набор общих правил или на этапе отладки решения мы увидели кучу ошибок, выходящих за границы изначально составленной формулы. Этот способ позволяет зафиксировать уже работающие варианты решения, а также неработающие (или содержащие ошибки). Это особенно полезно, если возникают так называемые «плавающие» ошибки. Плавающая ошибка очень неприятна тем, что как бы исправив ее в одном частном случае, ошибка вылезает в другом частном случае. Другими словами это, когда: после проверки было: S1 + R1 = А2 (неправильно), а S1 + R2 = А2 (правильно) после исправления стало: S1 + R1 = А1 (правильно), а S1 + R2 = А1 (неправильно) Таким образом, наша ошибка уплыла из случая S1 + R1, но приплыла в случай S1 + R2. У некоторых программистов плавающие ошибки порождают иллюзию, что руководитель проекта придирается к реализации и «придумывает на ходу» новые вводные. В то время как виной всему на самом деле неправильно заданные правила, вызывающие миграцию багов из одного частного случая в другой. Для руководителя проекта такие ошибки - страшный сон, ведь по мере столкновения с ними, возникает перспектива повторного тестирования всего проекта! В то же время программист просто меняет условие в коде и ждет реакции. Мой совет руководителям: фиксируйте состояние системы в частных случаях, чтобы показать, что где-то в коде заданы неверные логические условия, которые заставляют нашу ошибку переплывать с места на место. При таком подходе снять с себя ответственность уже не получится, а это уже прямое указание на чью-то возможную некомпетентность или лень!  Понимаю, что вам, как руководителю, конечно, очень муторно описывать эти случаи и следить за ними. Частично или полностью эту задачу можно (и нужно!) поручить тестировщикам, но т.к. ответственность за проект несете вы - возможно именно вам придется в этом разобраться. К сожалению квалификация некоторых тестировщиков или масштабы ветвлений все равно не позволят нам описать все частные случаи, которые могут встретиться на практике. Так что здесь целесообразен только реальный пилотный запуск с постоянным мониторингом обратной связи от пользователей и латание дыр "на живую". Иначе проект вы рискуете так никогда и не запустить. Буду рад, если вы поделитесь в комментариях своим опытом борьбы с плавающими ошибками! Как решали подобные ситуации? Были ли конфликты на этой почве? Автор и ведущий персонального блога "ПРО-продукт" https://t.me/productmaster