Или как понять, когда остановиться Как-то раз мой коллега, лид разработки, после затяжного спора о том, что должно быть в системной спецификации, подошел ко мне и спросил: — Скажи, а зачем нам вообще нужны аналитики? — И действительно, зачем? – подумал тогда я и написал заявление Вопрос этот, как бы крамольно он ни звучал, очень правильный. Системный анализ, как фаза разработки приложения, присутствует всегда (даже если это системы класса «Hello, world»), а вот системный аналитик, как выделенная роль – нет. Выделение отдельной специальной роли работает точно так же, как и разделение труда в обычном производстве: для маленьких задач не целесообразно, для больших задач – оправданно. При таком разделении  системный аналитик забирает на себя часть задач и функций некоего «универсального» исполнителя задачи. Однако, подобное разделение труда имеет свою цену: это потеря знаний при коммуникации, более сложное управление процессом и др. В этой статье я хочу поделиться своим опытом: описать минусы крайностей и дать рекомендации по распределению обязанностей между системными аналитиками и разработчиками. Итак, нам нужен системный аналитик, который формирует требования и разработчик, который эти требования реализует в коде. Если спросить у любого разработчика, каким главным свойством должны обладать системные требования, он, скорее всего, скажет: «чтобы было понятно, что делать». И это проблема.  Заключается эта проблема в том, что между сбором и систематизацией требований (прямая и понятная задача аналитика) и непосредственно кодированием (прямая и понятная задача разработчика) есть область проектирования решения; задачи из этой области могут и должны выполнять обе роли.  Вопрос – как провести границу? Как выбрать такую степень детализации требований, при которых это будет максимально полезно разработчику и не будет содержать ненужной и избыточной информации? Начнем с описания сложностей, которые могут возникнуть, если степень детализации будет выбрана не оптимально. Под «глупым» и «умным» участником процесса я подразумеваю не интеллект или профессиональные навыки, а степень погружения в процесс проектирования и контроля над реализуемым решением. Аналитик формулирует только функциональные требования («система должна уметь…»), сама система для него представляется черным ящиком, она или умеет что-то, или нет. В этом случае проектирование самого решения перекладывается на плечи разработчика. К чему это может привести: Риск высокой стоимости решения. Аналитик не знает, какое из его требований реализуется просто и дешево, а какое – сложно и дорого; у него нет возможности в процессе формирования ожиданий у заказчика/пользователя предложить и защитить решение, которое решает бизнес-задачу не хуже, но стоит сильно дешевле.  Например, желание пользователя получить автоматически обновляемые данные на форме может стоить разработки сложного и дорогого механизма по отслеживанию изменений данных, при этом реализация обновления данных по нажатию кнопки будет на порядок проще; Риск попасть в технические ограничения. Аналитик не знает, привели ли ранее выставленные им требования к технологическим ограничениям в разрабатываемой системе. Разработчик может выбрать то решение или технологию, которые подходят для текущего набора требований; любое решение или технология накладывают ограничения – какие-то задачи решаются легко и удобно, какие-то сложно и дорого. Отсутствие понимания ограничений может привести к согласованию с заказчиком и выставлению практически нереализуемых требований; Недостаточная проработка. Для решения ряда задач, особенно интеграционных, требований уровня «система А должна запросить у системы Б такие-то данные» недостаточны: разработчику в этом случае придется на себя взять поиск или формирование интеграционного контракта, его согласовать и распространить в каком-то виде эти знания внутри собственной команды разработки. А это – не профильные для разработчика активности, которые мог бы взять на себя аналитик;  Неудобная форма подачи. В ряде случаев, для того чтобы требования были полными  и логичными, аналитик должен выбрать какую-то форму описания требований и описать их достаточно детально, фактически спроектировать решение. Если это решение не согласуется с архитектурой приложения, то, во-первых, разработчику придется тратить время и силы на перевод “писанины” в нужное ему знание, а во-вторых, сам аналитик будет тратить силы и время на те детали, которые никто не будет читать и использовать. Например, описание модели данных: аналитик описывает реляционную модель данных, создает дополнительные конструкции для связей, требования к отчетам пишет в виде SQL запросов, а разработчик, использующий объектную модель и ORM, вынужден это переводить;  Ограничения в тестировании.Тестировщик не сможет получить из требований такого уровня достаточно информации о том, как должна работать система - лишь о том, что она должна уметь, а это разные вещи. При таком подходе выше риск возникновения ситуации, при которой система требованиям формально удовлетворяет, но на практике решение не удобно или не оптимально. Другая крайность при распределении функций – это слишком большая степень свободы для аналитика в части проектирования решения. Аналитик описывает алгоритмы на псевдокоде, пытается оперировать такими абстракциями, как слои приложения, описывает какие-то сервисные механизмы, определяет типы данных и формат обмена данными внутри приложения, суть требований скрывается за предложенными решениями. У этого подхода тоже есть серьезные минусы: Нет возможности проверить корректность. Разработчик не видит картины в целом, не понимает, зачем он делает ту или иную задачу: ему приходит спецификация, содержащая алгоритм на псевдокоде, правильность/адекватность которого он не может проверить. Это повышает риск ошибки со стороны разработчика и не позволяет провести ревью (аналитики ошибаются и осознанное прочтение разработчиком документации позволяет это выявить); Избыточная проработка. Системная спецификация может содержать детальное низкоуровневое описание алгоритмов работы с данными, которые разработчик не будет реализовывать. Например, не нужно описывать алгоритм вычисления количества дней между двумя датами или дня недели по дате (привет школьные олимпиады) – для большинства таких задач есть готовые решения; Лишняя работа ради стройности описания. Хорошо и правильно, когда ТЗ или спецификация имеют примерно одинаковую глубину для всех функциональных блоков; в этом случае читающему проще понять, на какие вопросы документ может ответить, а на какие – нет. Этот подход очень быстро может затянуть аналитика в бессмысленный и беспощадный процесс описывания вообще всего на свете: как читать данные из файлов, как называть внутренние классы и т.п. Есть ряд задач, которые аналитик в большинстве случаев просто не должен описывать и сервисные/инфраструктурные функции – одна из них; Риск потери актуальности документации. В случае если разработка решит провести рефакторинг, заменить фреймворк или какой-то модуль в приложении, слишком «близкая к коду» спецификация может стать неактуальной и неверной, причем в большом объеме. В каком-то объеме спецификации будут устаревать в любом случае, это процесс - как инфляция, но если можно не усугублять, то нужно не отказываться от такой возможности; “Режим бога” и неадекватное восприятие границы компетенций. В ряде случаев аналитику может просто не хватить технических знаний или опыта, но так как он привык, что в его команде он «умный» и никто кроме него, он может поддаться соблазну изобрести свой собственный велосипед из костылей.  Этот аспект не совсем технический, но потому он особенно важен и коварен. Проблема оценки собственной компетентности вообще довольно остро стоит перед человечеством и системный анализ - не исключение. Нет на свете хуже статей, чем те, в которых поднимается проблема, а в качестве решения говорится, что все случаи разные и надо смотреть по ситуации. Я хочу привести несколько приемов и рекомендаций из своей собственной практики, которые оказались полезны и действенны.  Рекомендация первая. Она звучит настолько банально и скучно, что кажется, что в ней нет никакой магии (а она есть): спросите у своих разработчиков, что они хотят или не хотят видеть в документации. Тут штука в том, что если спросить в лоб, то в 99% случаев будет ответ «Ну, чтоб было понятно, что делать». Более эффективно будет встретиться с лидом команды (или с основными ее участниками) и проговорить несколько ключевых моментов, которые встречаются почти в каждом проекте, особенно, в корпоративной разработке.  Приведу некоторые из тех вопросов, которые я стараюсь проговорить при взаимодействии с новой командой. Архитектура приложения / стек технологий. Какой используется язык? Как выглядит приложение изнутри? Это монолит или набор сервисов? Если набор сервисов, то как взаимодействуют между собой? Что из себя представляет фронт-энд? Как лучше разделять логику между фронтом и беком? Нужно ли описывать REST API для фронта? …и еще десяток вопросов, которые появятся после ответов на указанные выше. Попробуйте визуализировать приложение, попросите нарисовать. Если ранее с таким не сталкивались, попробуйте вместе с разработчиком проговорить один какой-нибудь кейс. Например: «пользователь открывает форму, что-то вводит, сохраняет, получает результат. Расскажи, как это будет реализовано, какие компоненты будут задействованы, куда пойдут данные». Разбор одного такого кейса даст огромный прирост в понимании того, из каких частей состоит приложение и как их можно/нужно дорабатывать.  Модель данных. Как построено взаимодействие с данными? Это прямые SQL запросы из кода или работа с объектами? Используется не-SQL хранилище? А как с ним работать, что там хранится? Нужно ли в спецификации описывать классы с их атрибутами максимально близко к коду или лучше использовать логические абстракции? Если абстракции, то, как быть с типами данных, нужно ли указывать? Нужен ли маппинг классов на таблицы? Форматы сообщений для сервисов между компонентами системы: XML или json? Нужны ли xsd и json схемы? Нужны ли описания всех возможных ошибок для REST API? Насколько детальное описание взаимодействия нужно для подключения к внешним сервисам? Декомпозиция функциональных блоков. Как лучше делить? Описывать бизнес сценариями или самостоятельно выделять общие куски? Нужно ли бизнес-описание задачи? Будет ли оно полезно? Будут ли его читать? Нужны ли эскизы форм? Насколько детально? Нужны ли реальные размеры? Что позволяет UI фреймворк? Можно ли использовать «модальные окна»? Можно ли использовать веб-сокеты? Одна такая сессия с конкретными разработчиками вашей команды даст ответов больше, чем стопка книг по системному анализу, потому что это будут максимально релевантные ответы под конкретный проект с конкретными людьми. Опытный системный аналитик может очень хорошо и правильно сформулировать набор требований к системе – непротиворечивых, атомарных, исполнимых и так далее, но для того, чтобы они были реализованы, их нужно донести до разработчиков. И вот такой экспресс-опрос повысит эффективность коммуникации между аналитиком и разработчиком как мало что другое. Рекомендация вторая. Нужно смотреть по ситуации. Точную идеальную степень вовлечения определить невозможно (даже ретроспективно, после внедрения), но есть некоторые признаки, которые позволят понять, стоит ли пытаться захватить полный контроль над проектом или достаточно будет «система должна позволять…». Речь идет, конечно, не о крайностях, а об оттенках. На мой взгляд, следующие факторы говорят в пользу подхода «Умный аналитик – глупый разработчик»:  Приложение или крупный функциональный блок проектируются с нуля (т.е. начало проекта), у разработчиков еще нет понимания, как все будет реализовано Команда разработки относительно многочисленна (>3 человек), нужна точка консолидации знаний Разработчики имеют низкую или среднюю квалификацию Разработчики работают или удаленно, или не полный день, или были привлечены только на этот проект – у них нет особой экспертизы в данной бизнес области и, возможно, нет особой мотивации ее приобрести: «внедрил – ушел» В проекте большое количество интеграционных взаимодействий с другими системами – нужно все это координировать  В проекте очень часто меняются требования и нужна отдельная активность по управлению изменениями. Требования везде меняются, но иногда – настолько часто, что одно только отслеживание и учет изменений может занимать кучу времени Есть желание стать незаменимым членом команды и спекулировать на этом. Будем честны, это тоже аргумент. Подход «глупый аналитик – умный разработчик» оптимален, как можно догадаться, в противоположных случаях: Аналитик подключается на фазе доработки или поддержки уже имеющейся системы, у команды сформирован подход и принципы разработки, они хорошо знают систему и им нужны только функциональные требования Разрабатываемая система довольно изолированная, каждый разработчик в команде со временем становится владельцем почти полного набора знаний о ней Практикуется подход итеративной/водопадной разработки, когда у команды разработки есть время спокойно спроектировать все, все новые функции аккуратно вписать в имеющуюся архитектуру. Казалось бы, как связаны методология разработки и степень вовлечения аналитика? Мой опыт показывает, что когда набор требований (хотя бы примерно) известен на целый релиз вперед, внутри команды (здесь я имею в виду и аналитиков и разработчиков) формируется некоторое общее видение решения и сильно большая и глубокая детализация не то, чтобы вредит – просто не требуется. У недостаточно детальных требований есть свои недостатки, но на подготовку релиза в такой размеренной и спокойной ситуации они имеют меньшее воздействие. Аналитик подключается частично, не на полное время или для решения какой-то конкретной задачи. Переделывать или ретроспективно документировать все что можно - не лучшая идея. Аналитик имеет низкую техническую квалификацию. В системном анализе, как в медицине, главное – не навредить. Если вы не понимаете, как на низком уровне работает какой-то механизм, не пытайтесь изобрести для него собственный алгоритм; скорее всего, разработчик не будет его реализовывать, а использует какую-нибудь готовую библиотеку. Разумеется, для вас это сигнал к тому, что хорошо бы понять принцип его работы, но если это не удается сделать быстро – то лучше в другой раз В проекте всего один разработчик, сильный, все знает и умеет и от вас нужны только функциональные требования. Может быть немного обидно, но если вспомнить, что миссия системного аналитика как роли – повысить эффективность разработки, то в том, чтобы вовремя остановиться, больше профессионализма, чем в попытке (пусть и успешной) доказать, что вы бы могли спроектировать не хуже, а то и лучше.  Рекомендация третья. Спросите у разработчиков по итогам некоторого периода совместной работы, все ли им понравилось и нести ли десерт. Как правило, если разработчик получает необходимую ему информацию из спеки или ТЗ, он этим остается доволен, а лишнее просто игнорирует или приспосабливается к трансформации написанного в нужное. Выяснив по итогам релиза или какой-то крупной итерации, что было удобно и полезно, что было лишним, а что лучше излагать по-другому, можно сделать взаимодействие в последующих итерациях сильно более эффективным; там, как правило, выясняется, что часть вещей, которые вы описывали каждый раз, они давно не читают, на степень детализации это не влияет и можно в будущем просто сэкономить время. Причем, если договариваться о правилах игры надо с лидом, то получать обратную связь лучше от рядовых разработчиков, так как лид сам может всего этого не прочувствовать. Кроме того, если лиду что-то не понравится, он, скорее всего, скажет сам, а рядовой исполнитель – нет.  Мне вот, после пары таких сеансов обратной связи, хотелось сказать: «что ж ты молчал все это время?» Если история про «захватить проект и спекулировать на этом» - ваш случай, то положительная обратная связь только усилит ваши позиции: все всегда сможете сослаться на мнение команды разработки, заявив, что ваши решения проверены временем и их эффективность подтверждена командой.  На этом, пожалуй, все. Хочу еще раз обратить внимание, что как бы это ни звучало, но при разработке ПО в качестве роли системного аналитика быть полезным  лучше, чем быть «умным» - как по мне, так это самый главный признак профессионализма. Системный архитектор