Функциональность и мастерство владения предметной областью

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

Но этот метод обязательного рисования функциональных диаграмм существует отнюдь не для всех видов систем. Так, в программной инженерии функциональные/потоковые диаграммы в большинстве проектов рисовать не принято, равно как не принято делать подобные текстовые описания (а хоть и псевдокодом). То есть программисты думают о функциональности своих программ, но принципиальных/концептуальных схем их работы программисты почему-то не делают, они держат обрывки этих принципиальных схем исключительно в уме --- и поэтому в этих схемах нельзя найти пробелы, ошибки, поговорить о функционировании их систем с коллегами. В исходном коде программ эти схемы не видны: парадигма программирования чаще всего не предполагает выделенного показа функциональности частей программы, плюс эта функциональность существенно зашумлена деталями описания, достаточным для исполнения кода. В передовых кругах разработчиков софта это не так, и функциональные описания (чаще всего получаемые в рамках практики domain driven design, DDD[1]) документируются, но пока это ещё не общепринятая культура/практика, скорее приятное и редкое исключение из общей практики.

Неработа с функциональностью --- типичная ошибка объединившихся в проекте инженеров и менеджеров-маркетологов (проект кто-то принёс! Значит там точно были маркетологи, продажники или просто инициативные инженеры, поэтому ещё нужно будет оценить рынок! Если проект принёс «инженер», то это вы так называете инженера-по-должности, но действовал он в роли организатора, инициирующего проект). «Техпредприниматели» или корпоративные менеджеры беседуют с внешними проектными ролями/stakeholders и выясняют обычно их потребности, а вот концепцией использования, то есть основными сценариями использования целевой системы не занимается вообще никто. В том числе в сценарии использования входят, заметим, не только happy path, то есть поведение системы, когда всё идёт хорошо и нет неожиданностей. Но неожиданности есть всегда, и о них нужно заботиться заранее. Инженер-проектировщик в таких случаях создаёт модульную конструкцию «на вырост» (сервисы, которые, по его мнению, могут дать всевозможные функции без дополнительных доработок продукта, если те вдруг потребуются). Для этого инженер соединяет через типовые интерфейсы из самых ходовых и простых стандартов типовые конструктивные элементы в надежде, что через восемь итераций всё как-то само-собой с функциональностью утрясётся (будет ведь обратная связь от недовольных клиентов!), и проект в конечном итоге получится успешным. Но это неэлегантно, не lean: добавляется лишняя функциональность, а нужной функциональности может в первых итерациях не оказаться. Заметим, что примерно так и срабатывает «испорченный телефон»: беседуют с клиентом одни люди (которые не обучены системной инженерии), а разрабатывают потом систему другие люди (которые обучены, но контакта с клиентом у них нет --- и концепция системы поэтому оказывается плоха).

Ошибку отсутствия функциональных частей системы в концепции системы тоже легко найти: в них при такой ошибке нет отражения предметной области, для которой целевая система осуществляет сервис. Сервис назван (уж как могут его назвать люди, занимающиеся целевой системой, а не надсистемой), а функция или функциональная часть в надсистеме (что выполняет модуль в составе надсистемы) --- нет. Например, в концепции информационной системы магазина появляется просто «база данных», а не «цены товарных позиций, правила предоставления скидок, история покупок». Понятно, что всё это должно где-то храниться, но не факт, что в нарисованной программистом на первой же его диаграмме «базе данных» (часть, например, может браться через API какого-то сервиса, а правила представления скидок могут храниться в настроечном файле или вообще оказаться искусственной нейронной сетью), и не факт, что даже «база данных» будет одна.

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

Объяснить программисту про необходимость делать функциональные описания в составе концепции системы трудно, ибо он мыслит модулями/продуктами/фреймворками/платформами, которые, по его мнению, абсолютно универсальны и поддержат «любую функцию». Любую-любую? Помним, что вы должны удваивать любой встречающийся в описаниях систем квантор всеобщности --- «каждый», «всякий», «любой», «все» и т.д. и ставить после этого вопросительный знак, сомневаясь в этой всеобщности. Всеобщности, увы, не случится. Но разочарование будет не в начале проекта, а поближе к концу --- когда окажется, что универсальных прикладных софтверных систем не бывает, так же, как и любых универсальных систем «железных», «человеческих», «культурных» и т.п.

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

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

У нас стоит задача тонкого химического синтеза диметилфторидметилхлорпентилбензолтитана для задач фармацевтической промышленности. Известно, что его трудно синтезировать, и при синтезе получается много примесей, от которых потом люди умирают. Поэтому мы предложим аптекам такой чистый продукт, от которого люди не будут умирать, а маркетинг будет оригинальный: через уборщиц медицинских учреждений, которые будут подбрасывать наши буклеты врачам, а также задушевно беседовать с пациентами в очередях ко врачам. Для того, чтобы получить чистый диметилфторидметилхлорпентилбензолтитан, мы будем использовать четыре стальных реактора, соединённых трубами диаметром 56мм, последняя труба с тефлоновым покрытием. Второй реактор закажем внешним контракторам. Чистоту получающегося диметилфторидметилхлорпентилбензолтитана будем отслеживать при помощи независимой экспертной службы. Все четыре реактора должны будут пройти проверку на выдерживание давления в 156 атмосфер.

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

Теперь представим инженера, которому маркетологи говорят, что ему нужно будет решить задачу химического синтеза, но непонятно ещё какую. И они когда-нибудь потом, но вот не прямо сейчас наймут химика, который всё уточнит. Инженер соглашается и берётся за дело: ему сразу понятно, что нужны будут реакторы и трубы. Реакторов непонятно сколько, ибо непонятно, сколько там в синтезе будет химических реакций. Поэтому лучше бы этих реакторов было побольше. Он выбирает цифру 4, как «не очень мало, но и ещё не очень дорого», догадывается, что в этом синтезе может быть хитрая эндотермическая реакция, но сам он для такой реакции реактор вряд ли спроектирует. Так что этот «хитрый реактор» он отдаёт проектировать внешним контракторам и честно об этом пишет. Хотя контракторы и спрашивали, что там с массами и температурой, ответ пока никто не может дать, поэтому контракт планируется без разговора о сценариях использования --- но контрактор, разумеется, от заказа не отказывается и говорит, что «сделаю любой реактор». Слово «любой» никого не отпугивает, ибо нет химика, который бы сказал, что же будет в этом реакторе происходить. Есть только инженеры по железу, хорошо разбирающиеся в марках стали и сварке, и маркетологи, беседующие с врачами и фармацевтами.

В случае железа реактора и труб всё тут очевидно: вероятность выпуска чистого диметилфторидметилхлорпентилбензолтитана в этой ситуации равна нулю. Но в случае софта почему-то кажется, что задачу так решать можно. И вот пишут про «сервера» и «базы данных», но каким образом там будет происходить обработка какой информации, и с чего бы эта обработка вдруг оказалась даже не лучше конкурентов, а вообще возможной, этого вопроса не возникает. Ровно как в предыдущей задаче, где нет химика, есть только сварщики и спецы по корпусам высокого давления. Они точно сделают софтверный «универсальный реактор»,но вот что там с чистотой «информационного вещества» или даже просто запуском нужной «информационной реакции» (слова«обработка информации» или «расчёт» так и пишутся, без малейших уточнений, какой именно), и получить исходные данные (или исходную информацию? данные! ибо информация что-то означает, а данные тут как сырьё --- можно игнорировать их содержание) --- это не к ним.

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

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

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

Сначала нужно разобраться с функционированием: что происходит в тот момент, когда система работает/функционирует (слово «функционирует» тут не случайно! Интересуют функции и функциональные части! Это предмет интереса тех ролей, которые отвечают за работу системы!), а не когда её собирают из размещаемых где-то конструктивных частей продуктов/модулей/изделий/платформ. Потом в порядке модульного синтеза всё равно нужно будет рассмотреть и конструктивные части, и размещения. Но это всё потом, а для начала нужно сделать качественную функциональную декомпозицию, функциональный/системный анализ.

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

Например, можно рассмотреть применение этих рассуждений к танцам. Просто махание ногами и руками (с запасом! Побольше махов, и сами махи пошире!) никого не устроит. Каждый мах должен быть понятен, зачем --- какая там эмоция, что этим махом хотят сказать, что продемонстрировать. Тогда и мах будет подобран соответствующий (резкий, плавный, объёмный или короткий, рукой или ногой --- ровно под необходимую функцию, а не «стандартный с бесчисленными вариантами из-за параметризации»). Если вам не нужно делать для вашего танца мах прямой ногой к уху («с запасом», подготовка классического балета, десяток лет тренировок), то вы можете сэкономить много лет жизни. Менее универсальные махи «под функцию», с учётом предметной области конкретного танца, тренируются много быстрее.

Мыслить только про конструкции нельзя. Отсутствие мышления о функциональности нужно как-то осознавать и исправлять. А это отсутствие мышления о функциональности заметно только в случае наличия системного мышления --- оно позволяет заметить то, о чём вы забыли подумать. Системное мышление управляет вашим вниманием, прежде всего оно направляет это внимание на функциональность систем: что делает система в составе надсистемы (первый вопрос), что делают подсистемы в составе системы (второй вопрос), только третий вопрос про «из чего сделана система».

А теперь внимательно посмотрите на свой текущий проект: не пропущены ли в нём функциональные рассмотрения? Если пропущены, то помним: без специалистов предметной области (subject matter expert)надсистемы, а потом и целевой системы, и её подсистем, и вашей системы (если она из систем создания) вам не разобраться. Общайтесь, общайтесь, общайтесь. Системные мыслители трансдисциплинарны, они много общаются с проектными ролями, отвечающими за самые разные прикладные практики.


  1. https://en.wikipedia.org/wiki/Domain-driven_design ↩︎