Про артефакты и коммуникацию

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

Тема — архитектурная документация в компании и ее унификация. Я это видел часто и уверен, что на эти грабли натыкаются очень часто — пытаются унифицировать артефакты архитектурных описаний, сформулировать «стандартные» требования к ним, и все такое. Я уверен, что в 80% случаев от этого будет больше вреда, чем пользы. И вот как развивался диалог на эту тему. «Ответ» — это мои реплики. «Вопрос» — реплики собеседников, иногда разных.


Вопрос:

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

Функциональный дизайн — сценарии использования, описание функций (как работает, какие ограничения, какие параметры) и объектная модель (модель данных на уровне бизнес объектов, не разложенная по плоским таблицам)
Архитектурный дизайн — HLD (слои, компоненты, грейды и свойства компонентов), Workflows (взаимодействие между компонентами поверх HLD)
Системный дизайн (API/Events, диаграммы последовательности и схема данных + маппинг в случае интеграционных компонентов)

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

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

Как вы строите флоу и какие артефакты считаете минимально необходимыми, чтобы каждый из этапов резал максимум рисков?


Ответ:

Такие, чтобы команда(-ы) разработки не ушла в неправильную сторону. Если сроки жесткие, то действуем не по шаблончикам и списочкам, на это нет времени, а по живой коммуникации с каждой командой. Новый артефакт добавляется в конкретном месте тогда, когда видна его необходимость, а не «чтобы был».Т.е. когда видно, что лиды плохо понимают, буксуют, не могут декомпозировать дизайн на задачки для спринтов. Конечно, с чего-то можно начать и заранее, но обычно времени хватает только на минимум. И конечно, очень зависит от характера проекта. В одном — сплошные sequence diagrams, потому что в них основная сложность. В другом проекте их нет вообще, не нужны, все по-другому работает, зато акцент на маппинг данных в разных системах. И от компетентности команд, конечно, тоже зависит. Одним нужно все разжевать и в рот положить, другие сами у тебя рвут шапку архитектора и готовы дизайн отдельных сервисов придумать и описать сами.


Вопрос (с неожиданным переиначиванием смысла):

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


Ответ:

А кто сказал «без документации»? Вроде как раз обсуждали, _какая_ документация нужна. Контекст, задачи, и проблемы определяют, какая нужна коммуникация и какая документация будет помогать в этой коммуникации.


Вопрос:

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


Ответ:

Почему? Скорее всего, если она не будет разная, то она не является «минимально необходимой» 😉


Вопрос:

Разная документация на разные компоненты убьет любой онбординг. Для этого можно было прийти почти в любой банк 5-7 лет назад и понять что базу знаний можно впринципе не смотреть


Ответ:

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

Можете объяснить механизм, каким образом «убивается онбординг», если мы про каждый компонент рассказываем самое важное, а не все по списочку?


Вопрос:

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


Ответ:

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


Вопрос:

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


Ответ:

Понятно, что потребители разные. Но это не умаляет мой тезис никак: «минимально необходимая документация» несовместима с «стандартизованным набором артефактов». Выберите что вам милее.


Вопрос:

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


Ответ:

Ну может не для самого «адаптера», а для нескольких компонентов, включая «адаптеры», _если_ они реализуют нетривиальное по последовательности взаимодействие, чтобы его можно было понять. Да и про маппинг — одной команде надо реально пример SQL написать, иначе накосячат сто пудов, для другой это будет совершенно лишнее. Если у вас все однотипное, и компетенции тоже выровнены — ваше счастье, стандартизация принесет больше пользы и меньше вреда. Но не всегда так, и уж точно не так от компании к компании. Стандартизация, внедряемая при большом разнообразии, может принести больше вреда. А «минимальное необходимое» всегда предельно контекстуально, по месту, иначе оно не будет минимальным.


Вопрос:

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


Ответ:

Ну то есть мы изначально предполагаем, что коммуникация не налажена или отсутствует, чинить это не хочется, а избыток документации должен это компенсировать? Инженерный подход 🙂 Боюсь, вы не прочитали то, что я противопоставлял этой идее. Не то, что «владелец посчитает важным» — это опять было бы свидетельством разорванной коммуникации — а то, что реально важно, т.к. проявляется как проблема. Я говорил тогда про взаимодействие архитектора и команды разработки, там расстояние меньше и время короче и взаимодействие теснее. С межкомандной документацией проще в том смысле, что там нужны больше черные ящики — API, внешние структуры данных, такое. Но сложнее в том, что потребителей больше, взаимодействия реже, коммуникация не такая плотная. Но общий принцип того, что документация это только один из инструментов для построения коммуникации — сохраняется. Если задаться вопросом, легко можно узнать, какой документацией пользуются, а какой — не хватает. Запросить обратную связь, устроить митап, сходить ногами и поговорить. Что-то можно включить и в стандарт, конечно, для того или иного типа API, если абсолютно понятно, что это необходимо. Но все-таки в целом я бы рекомендовал стандартизовывать и требовать наличие процессов коммуникации и удовлетворенности потребителей этой коммуникацией. А документация подтянется как следствие, причем именно та, которая нужна и востребована, а не «по стандарту».


Вопрос:

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

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


Ответ:

И опять мне не удается донести главную мысль, и считывается неверно. Никто не предлагает заменить личным общением документацию. Документация — очень эффективный инструмент коммуникации, тупо его не использовать. Тезис совсем в другом: наша цель — организовать эффективную коммуникацию. Эффективная коммуникация является в данном случае целевой системой. Документация будет являться составляющей частью этой системы, скорее всего и чаще всего — необходимой частью. Личное общение также очень полезно как составляющая часть коммуникации. Но отношение именно такое — коммуникация как система, документация и общение и другие способы коммуникации — как элементы, части, инструменты. Ну и далее — главный принцип — проектирование и оптимизацию ведем от целого, а не от части. Поэтому сперва смотрим на целое — кто участники коммуникации, какие особенности времени и места и контента, какие есть ограничения, какие целевые показатели качества этой коммуникации, какие есть проблемы. А после этого спрашиваем: какие нам нужны части/инструменты в организации коммуникации, чтобы стало лучше?
Кстати, хорошее замечание про софт-скиллы инженеров и естественные барьеры к общению. Так вот это тоже надо класть как объективные свойства человеческого материала при орг-проектировании и думать, как нивелировать негативный эффект, не ломая людей, и все же обеспечить эффективную коммуникацию. Решение — «только документы» — скорее всего, сильно неоптимальное.


Но снова и снова собеседники ошибочно полагают, что коммуникация — это и есть «личное общение» и противопоставляют коммуникацию документам.

Вопрос:

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


Подведем итог

Запомните это как мантру: документы и другие артефакты — это инструмент в коммуникации

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

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

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

И попробуйте вместо стандартов на артефакты сделать стандарт на направления и качество коммуникации. А уж какими артефактами она будет поддержана в каждом конкретном случае — может быть весьма ситуативно. Полезно иметь альбом шаблончиков, для того, чтобы участники могли подобрать что-то, что им подойдет, как tool box. Но не как стандарт, за исключением ну очень одинаковых и типовых ситуаций. Например, может быть стандарт на описание синхронных HTTP-based API, но никак не стандарт на описание архитектуры систем, если вы занимаетесь самой разной прикладной разработкой.

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

Как думать об ответственности архитектора?

Интересный факт, что рано или поздно в любом чате про архитекторов возникает примерно такой фрагмент диалога:

Собеседник 1: Архитектор должен брать на себя ответственность за качество всего проекта.
А из этого вытекает — должен иметь право на принятие решения, иметь право распоряжаться некоторым объёмом ресурсов для рефакторинга.

Собеседник 2: Это лютый бред. Нет у архитектора никакой ответственности, и соответственно, никаких решений, кроме мелких технических, он принимать не может. Ответственность есть у того, кто владеет ресурсами и бюджетом, и это не архитектор. Про тех, кому нравится думать про ответственность на позиции архитектора, можно сказать одно: она для них никогда не наступала.

Оставим в стороне безапелляционную форму реплики №2, и сконцентрируемся на одном крайне важном моменте: собеседники вкладывают совершенно разный смысл в термин «ответственность«. Для Собеседника 1 «ответственность» — это то, что берут на себя. Для Собеседника 2 «ответственность» — это то, что «наступает».

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

Так получилось, что я с этим вопросом разбирался детально сразу после разбирательства с понятием архитектуры. И немудрено, потому что если вы разобрались, что такое архитектура, но не разобрались, что такое деятельностная ответственность — вы не можете описать позицию архитектора. Мыкаетесь, описываете задачи, функции, и чувствуете, что все это не то, и категорически недостаточно. Пока не доберетесь до заветного «отвечает за«, и не разберетесь с этим хорошенько.

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

Я: Не надо путать административную ответственность и деятельностную. Слово одно, смысл совсем разный, второе бывает без первого, и в организации в первую очередь нужно второе, а не первое. Рассказывал об этом тут: https://bespalchuk.ru/presentations/goal-and-responsibility
Роль архитектора предусматривает наличие весьма широкой д.ответственности — за качество и своевременность принятия, согласования, трансляции архитектурных решений. Подкреплено ли это а.ответственностью и какого масштаба — это вопрос вторичный.

То, о чем говорите вы — это скорее административная (пост-фактумная) ответственность. Если вы не видите за этим словом второго, совсем другого понятия, вы упускаете главное и говорите только про второстепенное, которое вовсе не так интересно и важно.

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


Собеседник 2 (продолжает описывать а.ответственность): Ответствнность — это всегда «когда есть что терять». Другое дело, что некоторых только угроза жизни заставляет о чем то думать, а некоторый — недобрый взгляд начальника / жены.


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


Собеседник 3 (тоже зацепился за постфактумную половинку значения термина отв.): А почему тогда «отвественность» вдруг становится именно «ответственостью» если после ее наступления для человека ничего не меняется?


Я: Еще раз, это как функция и реализация — вроде как про одно, но вообще-то про разное. Вас опять сносит на мотив, хотя это десятое дело, важнее наличие/отсутствие поведения/мышления/фокуса внимания (д.отв). Вторичный вопрос, каким мотивом это поведение обеспечивается. Ну и даже обсуждая альтернативные мотивы типа профессиональной гордости, репутации, социальных норм, вы вынуджены их подводить под а.отв типа «человек не хочет, чтобы его мучала совесть». Хотя проще разлепить эти вещи (кстати, это не я придумал, можете и в википедии почитать про проспективную/ретроспекттвную отв.), и после этого сказать, что д.отв может обеспечиваться наказанием (а.отв), но может и другим — причастностью, профессионализмом, социальностью, etc. Сразу картинка становится богаче. А самое важное, что организация в первую очередь строится из д.отв, как «круги» в социократии. А не из наказаний. Совсем другой залог рассуждения и орг-проектирования. Я уверен, между собой с коллегами вы обсуждаете разделение ваших ответственностей в терминах «кто за что», а не «кто чем», не так ли? 🙂
Еще одна очень простая и понятная модель — волейбол. Что важнее и первее — договориться о том, где чья зона под сеткой, за которую отвечает тот или иной игрок, или «как кто будет наказан»? 🙂


Собеседник 2 (продолжает упорствовать и ввел еще редукционистскую «первичность») мотив первичен. Без мотива человек не встанет с дивана. А про волейбол — мотив победить. Нет такого мотива — да ваще можно на площадку не выходить, пусть техническое поражение защитают


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


Собеседник 2 (отказывается слышать): из лекции следует, что наличие мотива вторично для деятельности, что является неправдой.


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


Собеседник 2: понимая механизм, я могу додумать более высокоуровневую абстракцию. Если я знаю только абстракцию, без механизма, то переодически я буду иметь проблемы с объяснением происходящего.


Я: Согласен с вами. Точно также как проектирование систем сверху вниз всегда дополняется проходами снизу вверх, а functional view дополняется development view’шкой. Я готов смягчить свои слова по поводу важности, но стою на полезности разлепления 🙂 Уверен, что мы уже потренировались достаточно, чтобы прочитав сегодняшнее обсуждение с самого начала уже стало четко заметно, где произошел перескок с разговора о д.отв на разговор об а.отв. Главный тезис, который, на мой взгляд, становится очевидным после разлепления — архитектор может быть офигенно ответственным за многое (в смысле д.отв), даже если он не отвечает ничем материальным (а.отв), мотивы/механизмы обеспечения д.отв могут быть и другими. То есть одновременно — «ответственность есть» и «ответственности нету» — это классическая ситуация, когда надо разлеплять понятия, расщеплять на два.


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


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

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


Собеседник 4 (все еще не разлепил А и Д): Погоди. Ну давай представим: мы пошли в поход компанией. Кому то было поручено взять с собой например те же спички. И он не взял. Просохатил, без злого умысла. Отвественность наступит? — БЕЗУСЛОВНО ДА!


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

Друзья, еще раз, обратите внимание, это не я придумал, это все в википедии тоже написано 🙂 Буквально «ученые изучают этот мутный вопрос, но уже выделяют несколько значений/видов ответственности «.

А еще через пару десятков реплик с другими собеседниками мы вдруг видим:


Собеседник 2: Теперь уже ты наглухо игнорируешь ответственность, как наказание, как одно из значений слова. Чтобы избегать путаницы, предлагаю заменить твою часть на «добросовестную работу«, а мою часть на «получение люлей«.


Я (влезаю опять): Ага. Именно. Оно и есть. «Проспективная» (думай наперед и подкладывая соломку) и «ретроспективная» (получай люлей) ответственность — другие «научные» названия того же самого, о чем я тут распинался. Вроде вышли на различение как минимум в кейсах, ура! Осталось убедить, что когда слева — крякает, плавает, откладывает яйца и в перьях, а справа — кормит детенышей молоком, на голове — рога, на четырех ногах — копыта и живет в лесу, то можно конечно и то и это назвать одним словом «дичь» и подать в составе одного блюда на стол, но в огромном числе других жизненных ситуаций лучше называть разными словами. 🙂
И тогда не будет воспроизводиться этот самый антипаттерн в чатиках «— Архитектор отвечает за это и за это. — Это бред, архитекторы никогда ответственности не несут!«, с которого начался и наш разговор вчера.

ChatGPT дизайнит

Ну что же, я добрался до ChatGPT, и, признаться, я поражен. Почитав многочисленные примеры, я был уверен, что все-таки выход бота — это такая «средне-статистическая по всей больнице по всему миру отвечалка на известные вопросы». И был уверен, что если попробовать заставить этого бота дизайнить что-то более конкретное, частное, нетиповое, то будет получаться фигня. Признаю, я был неправ. Хотя может быть реально очень сложно сегодня найти что-то «нетиповое» 🙂 

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

Продолжу эксперименты на досуге, а пока приглашаю вас подивиться на это:


Me: I need to deisgn a computer program, using the component-based approach. The requirements are to read files from the folder as soon as they appear, parse them as CSV files, group by the values of the first column, sort groups by the values of the second column in each group, and write down the outgoing files separately for each group. Which interconnected components this program could contain at the top level of design?
 
AI: A computer program that reads files from a folder as soon as they appear, parses them as CSV files, groups them by the values of the first column, sorts the groups by the values of the second column in each group, and writes the outgoing files separately for each group can be designed using the component-based approach as follows:
  1. File System Monitor: This component monitors the designated folder for any new files that appear. As soon as a new file appears, it is passed on to the next component for processing.
  2. CSV Parser: This component is responsible for parsing the incoming files as CSV files. It extracts the data from the CSV file and passes it on to the next component for further processing.
  3. Data Grouping: This component groups the data by the values of the first column. It creates separate groups for each unique value in the first column.
  4. Data Sorting: This component sorts the data within each group by the values of the second column.
  5. File Writer: This component is responsible for writing the outgoing files separately for each group. It creates a separate file for each group and writes the data for that group to the corresponding file.

These are the top-level components that can be used to design a computer program to meet the given requirements.

Me: How these components could be connected? Which connections do I need, and which components would be not connected?
 
AI: The components can be connected as follows:
  1. File System Monitor -> CSV Parser: The File System Monitor component passes the new files to the CSV Parser component as soon as they appear.
  2. CSV Parser -> Data Grouping: The CSV Parser component passes the parsed data to the Data Grouping component, which groups the data by the values of the first column.
  3. Data Grouping -> Data Sorting: The Data Grouping component passes the grouped data to the Data Sorting component, which sorts the data within each group by the values of the second column.
  4. Data Sorting -> File Writer: The Data Sorting component passes the sorted data to the File Writer component, which writes the outgoing files separately for each group.

In this design, the File System Monitor, CSV Parser, Data Grouping, Data Sorting, and File Writer components are interconnected. There are no components that are not connected.

This is just one possible way to connect the components to meet the given requirements. There may be other ways to design the program and connect the components. It is up to the designer to choose the approach that best fits their needs.

Me: How these components could pass data between each other?
 
AI: There are several ways that the components can pass data between each other. Some options include:
  1. Using function calls: One component can pass data to another component by calling a function provided by the second component and passing the data as an argument. The second component can then process the data and return any relevant results back to the first component.
  2. Using shared memory: The components can share data by storing it in a shared memory location that is accessible to all of the components. This can be implemented using a shared database or a shared file system.
  3. Using message passing: The components can pass data to each other using a message-passing interface. Each component has a unique identifier and can send messages to other components by sending the message and the identifier of the intended recipient. The recipient component can then receive the message and process the data.
  4. Using a publish-subscribe model: In this model, one component publishes data to a message queue, and other components can subscribe to the queue to receive the data. This allows the components to communicate asynchronously, without the need for direct function calls or shared memory.

These are just a few examples of how the components can pass data between each other. The choice of which approach to use will depend on the specific requirements and constraints of the program.

Me: What would be the best option of communication mechanism if the program have to process files as quick as possible and the files are maximum 1Gb of size?
 
AI: If the program needs to process files as quickly as possible and the files are maximum 1Gb in size, using a shared memory location or a message-passing interface may be the best options for communication between the components.

Using function calls or a publish-subscribe model may not be as efficient in this case, as they involve additional overhead such as the need to create and send messages or the need to serialize and deserialize data. This additional overhead can slow down the processing of the files.

Shared memory or message passing can allow the components to communicate directly and transfer data more efficiently. However, it is important to consider the trade-offs between these options. Shared memory may be more efficient for communication, but it can also be more complex to implement and may require additional synchronization mechanisms to ensure that the data is accessed correctly by multiple components. Message passing can be simpler to implement, but it may have higher overhead due to the need to send and receive messages.

Ultimately, the best option will depend on the specific requirements and constraints of the program. It may be useful to implement and compare multiple approaches to determine which one provides the best performance.

Me: And what if the computer memory, available for the program, is just 500Kb?
 
AI: If the computer memory available for the program is only 500Kb, it may not be feasible to use shared memory or a message-passing interface for communication between the components. These approaches typically require larger amounts of memory to store the data being shared or the messages being passed.

In this case, using function calls or a publish-subscribe model may be a better option for communication between the components. These approaches can allow the components to communicate asynchronously, without the need to store large amounts of data in memory.

It is important to note that the limited memory available may impact the performance of the program and may require additional design considerations to ensure that the program is able to process the files efficiently. For example, the program may need to process the files in smaller chunks to avoid running out of memory, or it may need to use more efficient data structures to minimize the amount of memory required.

It may also be necessary to consider additional optimization techniques such as minimizing the number of copies of data that are made, using compressed data formats, or using techniques such as lazy evaluation to avoid unnecessary processing. These techniques can help to minimize the memory usage and improve the performance of the program.

 
Me: Having the abovementioned constraints, how could the interface of Data Grouping component look like?
 

AI: The interface of the Data Grouping component could look something like this:

class DataGrouping:
def __init__(self, group_key_column: int):
"""
Initialize the DataGrouping component.

Parameters:
- group_key_column: The index of the column to use as the key for grouping the data.
"""
pass

def group_data(self, data: List[List[Any]]) -> Dict[Any, List[List[Any]]]:
"""
Group the data by the values in the specified column.

Parameters:
- data: A list of lists containing the data to group. Each inner list represents a row of data.

Returns:
A dictionary mapping the unique values in the group key column to the corresponding rows of data.
"""
pass
This interface defines a class called DataGrouping with two methods: __init__ and group_data. The __init__ method is used to initialize the component and specify the column to use as the group key. The group_data method is used to group the data by the values in the specified column and return the results as a dictionary mapping the unique values in the group key column to the corresponding rows of data.

The DataGrouping class could be used as follows:

data_grouping = DataGrouping(group_key_column=0)
grouped_data = data_grouping.group_data(data)

In this example, the DataGrouping component is initialized with the group key column set to 0, and the group_data method is called to group the data. The resulting grouped data is returned as a dictionary.

This is just one possible design for the interface of the Data Grouping component. The specific details of the interface will depend on the specific requirements and constraints of the program.

 
Me: But we stated that the data piece from the file can outnumber the amount of free memory. The proposed interface require that the full set of data stored in memory.
 
AI: You are correct that the proposed interface for the Data Grouping component assumes that the full set of data can be stored in memory. If the data piece from the file can outnumber the amount of free memory, this may not be feasible.

To address this issue, one approach would be to modify the interface of the Data Grouping component to allow the data to be processed in smaller chunks. For example, the group_data method could be modified to take an additional parameter chunk_size that specifies the number of rows to process at a time. The method could then process the data in chunks, grouping the data for each chunk and returning the results incrementally.

Here is an example of how the modified interface could look:

class DataGrouping:
def __init__(self, group_key_column: int):
"""
Initialize the DataGrouping component.

Parameters:
- group_key_column: The index of the column to use as the key for grouping the data.
"""
pass

def group_data(self, data: Iterable[List[Any]], chunk_size: int) -> Iterable[Tuple[Any, List[List[Any]]]]:
"""
Group the data by the values in the specified column.

Parameters:
- data: An iterable containing the data to group. Each element of the iterable represents a row of data.
- chunk_size: The number of rows to process at a time.

Returns:
An iterable yielding tuples containing the group key and the corresponding rows of data.
"""
pass

In this modified interface, the group_data method takes an iterable of data rather than a list, and it returns an iterable of tuples containing the group key and the corresponding rows of data. The chunk_size parameter specifies the number of rows to process at a time, allowing the data to be processed in smaller chunks to fit within the available memory.

This modified interface can be used as follows:

data_grouping = DataGrouping(group_key_column=0)
for group_key, group_data in data_grouping.group_data(data, chunk_size=1000):
# Process the grouped data for the current chunk
pass

In this example, the DataGrouping component is initialized with the group key column set to 0, and the group_data method is called with a chunk size of 1000. The method returns an iterable that yields tuples containing the group key and the corresponding rows of data for each chunk. The data can then be processed in smaller chunks to fit within the available memory.

This is just one possible approach to modifying the interface of the Data Grouping component to allow the data to be processed in smaller chunks. Other approaches may also be possible, depending on the specific requirements and constraints of the program.

Me: Which second-level components could we have inside of the File System Monitor component?
 
AI: The File System Monitor component is responsible for monitoring a designated folder for new files and passing them on to the next component for processing. Some second-level components that could be included inside the File System Monitor component are:
  1. File Watcher: This component is responsible for monitoring the designated folder for any changes, such as the creation of new files or the deletion of existing files. It can use APIs provided by the operating system or a third-party library to monitor the folder for changes.
  2. File Filter: This component is responsible for filtering the list of files in the designated folder based on specific criteria. For example, it may only pass on files with a certain file extension or files that meet certain size or date criteria.
  3. File Queue: This component is responsible for maintaining a queue of the files that have been identified by the File Watcher and filtered by the File Filter. It can store the files in memory or in a persistent storage location such as a database.

These are just a few examples of second-level components that could be included inside the File System Monitor component. The specific components included and their design will depend on the specific requirements and constraints of the program.

It is also possible to have additional layers of components within the File System Monitor component, depending on the complexity of the program. For example, the File Watcher component could be further divided into subcomponents responsible for specific tasks such as monitoring the folder for changes or handling events triggered by the operating system.

Me: If the File System Monitor component contain the File Queue component, maintaining the queue, which component would read items from that queue?
 
AI: If the File System Monitor component contains the File Queue component, which is responsible for maintaining a queue of the files identified by the File Watcher and filtered by the File Filter, another component would typically be responsible for reading items from the queue and processing them.

This component could be the CSV Parser component, which is responsible for parsing the incoming files as CSV files and extracting the data. The CSV Parser component could be designed to read the files from the queue and process them one at a time.

Alternatively, the File System Monitor component could include another second-level component called the File Reader, which is responsible for reading the files from the queue and passing them on to the CSV Parser component for processing.

The specific design of the program and the components within it will depend on the specific requirements and constraints of the program. It is up to the designer to choose the approach that best fits their needs.

Me: So what is the final list of the components inside of File System Monitor so far?

AI: Here is a list of the components that could be included inside the File System Monitor component so far:

  1. File Watcher: This component is responsible for monitoring the designated folder for any changes, such as the creation of new files or the deletion of existing files. It can use APIs provided by the operating system or a third-party library to monitor the folder for changes.
  2. File Filter: This component is responsible for filtering the list of files in the designated folder based on specific criteria. For example, it may only pass on files with a certain file extension or files that meet certain size or date criteria.
  3. File Queue: This component is responsible for maintaining a queue of the files that have been identified by the File Watcher and filtered by the File Filter. It can store the files in memory or in a persistent storage location such as a database.
  4. File Reader (optional): This component is responsible for reading the files from the queue and passing them on to the CSV Parser component for processing.

These are the components that could be included inside the File System Monitor component so far. The specific components included and their design will depend on the specific requirements and constraints of the program. It is possible to have additional layers of components within the File System Monitor component, depending on the complexity of the program.

Me: If the FIle Reader reads from the queue, does it mean that it has a separate thread of control?

AI: It is possible for the File Reader component to have a separate thread of control if it is implemented as a separate process or thread that runs concurrently with the main program. This can allow the File Reader component to read files from the queue and pass them on to the CSV Parser component for processing without blocking the main program.

Having a separate thread of control can be useful in cases where the File System Monitor component is expected to receive files at a high rate and process them in a timely manner. By running the File Reader component in a separate thread, the program can process the incoming files concurrently and potentially improve the overall performance.

Alternatively, the File Reader component could be implemented as part of the main program and be invoked periodically to read and process the files from the queue. This approach may be simpler to implement, but it may not be as efficient in cases where the File System Monitor component is expected to receive a high volume of files.

The specific design of the File Reader component will depend on the specific requirements and constraints of the program. It is up to the designer to choose the approach that best fits their needs.

Me: Let’s decide that File Reader has it’s own thread of control. How the CSV Parser is activated and what is the thread of control it runs in?

AI: If the File Reader component is implemented as a separate process or thread that runs concurrently with the main program, it can activate the CSV Parser component by passing the data to it as soon as it is read from the queue.

The CSV Parser component can be implemented as a separate process or thread, or it can be implemented as part of the main program. If it is implemented as a separate process or thread, it will have its own thread of control and will run concurrently with the main program and the File Reader component.

If the CSV Parser component is implemented as part of the main program, it will run in the same thread of control as the main program. In this case, the File Reader component can pass the data to the CSV Parser component by calling a function provided by the CSV Parser component and passing the data as an argument. The CSV Parser component can then process the data and return any relevant results back to the File Reader component.

The specific design of the CSV Parser component and the approach used to activate it will depend on the specific requirements and constraints of the program. It is up to the designer to choose the approach that best fits their needs.

Me: What the CSV Parser does with the data, returned from the CSV Parser?

AI: It is up to the designer to decide what the CSV Parser component does with the data returned from the CSV Parser component. Some possible options include:

  1. Storing the data: The CSV Parser component could store the data in a shared memory location or a database for use by other components.
  2. Sorting the data: The CSV Parser component could sort the data based on the values in a specific column, as specified in the requirements.
  3. Grouping the data: The CSV Parser component could group the data based on the values in a specific column, as specified in the requirements.
  4. Writing the data to a file: The CSV Parser component could write the data to a file or files, either in the same format as the input files or in a different format.

These are just a few examples of what the CSV Parser component could do with the data returned from the CSV Parser component. The specific actions taken will depend on the specific requirements and constraints of the program.

Me: We decided above that CSV Parser will be connected with another, grouping component, didn’t we? How this connection will be used, before, after or upon File Reader calling a function provided by CSV Parser?
 
AI: In the previous examples, it was suggested that the CSV Parser component could be connected to another component, such as a Data Grouping component, to perform additional processing on the data.

There are several ways in which the CSV Parser component and the Data Grouping component could be connected and interact with each other. Here are a few possible options:

  1. Before the File Reader calls a function provided by the CSV Parser: The Data Grouping component could be connected to the CSV Parser component before the File Reader component calls a function provided by the CSV Parser component. In this case, the CSV Parser component could pass the data to the Data Grouping component as soon as it is parsed and the Data Grouping component could process the data and return the results back to the CSV Parser component. The CSV Parser component could then return the results back to the File Reader component as usual.
  2. After the File Reader calls a function provided by the CSV Parser: The Data Grouping component could be connected to the CSV Parser component after the File Reader component calls a function provided by the CSV Parser component. In this case, the CSV Parser component could return the data back to the File Reader component as usual, and the File Reader component could pass the data on to the Data Grouping component for further processing.
  3. Upon File Reader calling a function provided by the CSV Parser: The Data Grouping component could be connected to the CSV Parser component such that it is activated when the File Reader component calls a function provided by the CSV Parser component. In this case, the CSV Parser component could pass the data to the Data Grouping component as part of the function call and the Data Grouping component could process the data and return the results back to the CSV Parser component as part of the same function call. The CSV Parser component could then return the results back to the File Reader component as usual.

The specific approach used to connect the CSV Parser component and the Data Grouping component and the order in which they are called will depend on the specific requirements and constraints of the program. It is up to the designer to choose the approach that best fits their needs.

Me: Could you provide the PlantUML sequence diagram for the interactions, described above?
 
AI: Here is a PlantUML sequence diagram for the interactions described above:
@startuml

actor FileReader
participant CSV_Parser
participant Data_Grouping

FileReader -> CSV_Parser : read_and_parse_data()
CSV_Parser -> Data_Grouping : group_data()
Data_Grouping --> CSV_Parser : grouped_data
CSV_Parser --> FileReader : parsed_and_grouped_data

@enduml

This sequence diagram shows the interaction between the File Reader component, the CSV Parser component, and the Data Grouping component when the CSV Parser component is connected to the Data Grouping component before the File Reader component calls a function provided by the CSV Parser component.

In this scenario, the File Reader component initiates the interaction by calling the read_and_parse_data function provided by the CSV Parser component. The CSV Parser component then passes the data to the Data Grouping component for further processing and receives the grouped data back from the Data Grouping component. Finally, the CSV Parser component returns the parsed and grouped data back to the File Reader component.

To represent the other interactions described above, the sequence diagram can be modified as follows:

@startuml

actor FileReader
participant CSV_Parser
participant Data_Grouping

FileReader -> CSV_Parser : read_and_parse_data()
CSV_Parser --> FileReader : parsed_data
FileReader -> Data_Grouping : group_data(parsed_data)
Data_Grouping --> FileReader : grouped_data

@enduml

This modified sequence diagram shows the interaction between the File Reader component, the CSV Parser component, and the Data Grouping component when the CSV Parser component is connected to the Data Grouping component after the File Reader component calls a function provided by the CSV Parser component.

@startuml

actor FileReader
participant CSV_Parser
participant Data_Grouping

FileReader -> CSV_Parser : read_and_parse_and_group_data()
CSV_Parser -> Data_Grouping : group

Me: This diagram doesn’t include the File System Monitor component, which triggers the whole process.

AI: You are correct that the PlantUML sequence diagram provided above does not include the File System Monitor component, which is responsible for triggering the process of reading, parsing, and grouping the data.

To include the File System Monitor component in the sequence diagram, we can modify the diagram as follows:

@startuml

participant File_System_Monitor
actor FileReader
participant CSV_Parser
participant Data_Grouping

File_System_Monitor -> FileReader : process_files()
FileReader -> CSV_Parser : read_and_parse_data()
CSV_Parser -> Data_Grouping : group_data()
Data_Grouping --> CSV_Parser : grouped_data
CSV_Parser --> FileReader : parsed_and_grouped_data

@enduml

This modified sequence diagram shows the interaction between the File System Monitor component, the File Reader component, the CSV Parser component, and the Data Grouping component when the CSV Parser component is connected to the Data Grouping component before the File Reader component calls a function provided by the CSV Parser component.

In this scenario, the File System Monitor component initiates the process by calling the process_files function provided by the File Reader component. The File Reader component then reads and parses the data and passes it on to the CSV Parser component, which passes the data to the Data Grouping component for further processing. The Data Grouping component returns the grouped data back to the CSV Parser component, which returns the parsed and grouped data back to the File Reader component.

To represent the other interactions described above, the sequence diagram can be modified as follows:

@startuml

participant File_System_Monitor
actor FileReader
participant CSV_Parser
participant Data_Grouping

File_System_Monitor -> FileReader : process_files()
FileReader -> CSV
Me: And what about other components, mentioned above? Both of the first and second-level components? Will they be included to cover the full file processing scenario up to writing the outgoing files? Could you provide UML plant sequence diagram for that?

AI: To include the other components mentioned above and cover the full file processing scenario up to writing the outgoing files, the PlantUML sequence diagram can be further expanded as follows:

@startuml

participant File_System_Monitor
actor File_Watcher
participant File_Filter
participant File_Queue
actor File_Reader
participant CSV_Parser
participant Data_Grouping
participant File_Writer

File_System_Monitor -> File_Watcher : start_monitoring()
File_Watcher -> File_Filter : filter_files()
File_Filter -> File_Queue : add_to_queue(filtered_files)
File_System_Monitor -> File_Reader : process_files()
File_Reader -> File_Queue : get_from_queue()
File_Queue -> File_Reader : file
File_Reader -> CSV_Parser : read_and_parse_data(file)
CSV_Parser -> Data_Grouping : group_data()
Data_Grouping --> CSV_Parser : grouped_data
CSV_Parser --> File_Reader : parsed_and_grouped_data
File_Reader -> File_Writer : write_data(parsed_and_grouped_data)
File_Writer --> File_Reader : success/failure

@enduml

This expanded sequence diagram shows the interactions between the File System Monitor component, the File Watcher component, the File Filter component, the File Queue component, the File Reader component, the CSV Parser component, the Data Grouping component, and the File Writer component.

In this scenario, the File System Monitor component starts the process by calling the start_monitoring function provided by the File Watcher component, which begins monitoring the designated folder for changes. When a change is detected, the File Watcher component passes the list of affected files to the File Filter component, which filters the files based on specific criteria. The File Filter component then adds the filtered files to the queue maintained by the File Queue component.

The File System Monitor component also initiates the file processing by calling the process_files function provided by the File Reader component. The File Reader component reads the files from the queue maintained by the File Queue component, one at a time, and passes them on to the CSV Parser component for parsing. The CSV Parser component passes the parsed data on to the Data Grouping component for grouping and receives the grouped data back from the Data Grouping component. Finally, the File Reader component passes the parsed and grouped data on to the File Writer component, which writes the data to the outgoing files.

Me: You missed the sorting component.

AI: You are correct, I apologize for the oversight. To include the sorting component in the PlantUML sequence diagram, we can modify the diagram as follows:

@startuml

participant File_System_Monitor
actor File_Watcher
participant File_Filter
participant File_Queue
actor File_Reader
participant CSV_Parser
participant Data_Sorter
participant Data_Grouping
participant File_Writer

File_System_Monitor -> File_Watcher : start_monitoring()
File_Watcher -> File_Filter : filter_files()
File_Filter -> File_Queue : add_to_queue(filtered_files)
File_System_Monitor -> File_Reader : process_files()
File_Reader -> File_Queue : get_from_queue()
File_Queue -> File_Reader : file
File_Reader -> CSV_Parser : read_and_parse_data(file)
CSV_Parser -> Data_Sorter : sort_data()
Data_Sorter --> CSV_Parser : sorted_data
CSV_Parser -> Data_Grouping : group_data(sorted_data)
Data_Grouping --> CSV_Parser : grouped_data
CSV_Parser --> File_Reader : parsed_and_grouped_data
File_Reader -> File_Writer : write_data(parsed_and_grouped_data)
File_Writer --> File_Reader : success
Me: Could you provide the component diagram in PlantUML for the top level of that design?

AI: Here is a PlantUML component diagram for the top level of the design:

@startuml

component File_System_Monitor {
component File_Watcher
component File_Filter
component File_Queue
}

component File_Reader {
component CSV_Parser
component Data_Sorter
component Data_Grouping
component File_Writer
}

File_System_Monitor --> File_Reader

@enduml

This component diagram shows the top-level components of the design: the File System Monitor component, the File Watcher component, the File Filter component, the File Queue component, the File Reader component, the CSV Parser component, the Data Sorter component, the Data Grouping component, and the File Writer component.

The File System Monitor component is connected to the File Reader component, which indicates that the File System Monitor component is responsible for triggering the file processing process and that the File Reader component is responsible for reading and processing the files.

The File Reader component is composed of the CSV Parser component, the Data Sorter component, the Data Grouping component, and the File Writer component, which indicates that these components are responsible for performing the specific tasks of parsing the data, sorting the data, grouping the data, and writing the data to the outgoing files, respectively.

This component diagram provides a high-level overview of the design and shows the relationships between the various components. It can be helpful for understanding the overall structure and organization of the program.

Me: But we designated sorting and grouping components to the first level, not to the second under file reader.

AI: You are correct, I apologize for the mistake. To correctly show the relationships between the various components, the component diagram can be modified as follows:

@startuml

component File_System_Monitor {
component File_Watcher
component File_Filter
component File_Queue
}

component File_Reader {
component CSV_Parser
}

component Data_Processor {
component Data_Sorter
component Data_Grouping
}

component File_Writer

File_System_Monitor --> File_Reader
File_Reader --> Data_Processor
Data_Processor --> File_Writer

@enduml

This modified component diagram shows the relationships between the File System Monitor component, the File Watcher component, the File Filter component, the File Queue component, the File Reader component, the CSV Parser component, the Data Sorter component, the Data Grouping component, and the File Writer component.

In this diagram, the File System Monitor component is connected to the File Reader component, which is responsible for reading and parsing the files. The File Reader component is connected to the Data Processor component, which is composed of the Data Sorter component and the Data Grouping component and is responsible for sorting and grouping the data. Finally, the Data Processor component is connected to the File Writer component, which is responsible for writing the data to the outgoing files.

This component diagram correctly shows the relationships between the various components and provides a high-level overview of the design. It can be helpful for understanding the overall structure and organization of the program.

Me: Why did you combined sorting and grouping components into something bigger?

AI: I combined the sorting and grouping components into a larger component called the Data Processor component because it can help to simplify the diagram and provide a clearer overview of the program’s structure and organization.

In the original design, the sorting and grouping components were at the same level and performed separate tasks that were connected through the CSV Parser component. By combining these components into a single component, we can more clearly show the relationships between these tasks and how they fit into the overall design.

It is generally a good practice to group related components together and to minimize the number of connections between components, as this can help to make the design simpler and easier to understand. However, it is ultimately up to the designer to decide how to best organize and structure the components to meet the specific needs of the program.


В этом месте я, надо сказать, просто устал, было заполночь, и в целом было понятно, что он так может еще долго, так долго, как я не могу 🙂

Субъективно и навскидку, я бы сказал, что тест Тьюринга с этой штукой пройден или почти пройден. Наверняка будут соответствующие попытки проверить статистически.

Кто хотел персонального Джарвиса как в фильме Железный человек? Ну может слегка тупенький, но все же — вот он. Думаю, что очень скоро программирование, дизайн, и очень многое еще превратится в увлекательный диалог, с голосовым вводом и быстрым визуальным выводом и в таком тандеме человека и машины действительно может быть достигнут резкий скачок эффективности интеллектуальной творческой работы, даже без претензии на то, что машина «делает сама все».

Про власть разработчиков

Выношу из чата архитекторов про «власть, которая то ли есть, то ли нету у разработчиков»:


…Это очень интересный вопрос. Казалось бы, у разработчиков, которые собственно, пишут код — власти очень много! Адизес, кстати, в таком же духе разъяснял про большую власть, которая есть у рядовых исполнителей. И иногда мы видим проявления этой власти — какие-нибудь экспериментальные фреймворки, всунутые куда надо и куда не надо. Но в другие моменты разработчик начинает спрашивать — а мне так сделать или эдак, и вот тогда ему прилетает ответ, и вдруг власть как будто исчезает. Боб Мартин в одном хорошем своем цикле встреч на этот вопрос про техдолги и рефакторинг и тесты отвечал так — никогда, ни при каких обстоятельствах не показывайте тесты или рефакторинг как отдельные строки затрат менеджменту, это ваша поляна и ответственность — как написать или изменить код. Если вы это покажете, вам это вырежут и вы будете без тестов и без рефакторинга, и как раз и превратитесь в безвластных г..кодеров. Я думаю, что в этом есть смысл, и на самом деле у разработчиков очень много власти. Архитектор, кстати, это чувствует очень хорошо, потому что ты ж явно говоришь и пишешь сделать одно, а они делают другое 🙂 Нужно только научиться об этой власти вспоминать и правильно к ней относиться, разумно использовать.

Системные аналитики и архитекторы

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

Я там ответил, и сохраню это тут, слегка расширив и углубив.


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

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

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

Все эти споры — от попытки найти универсальный оптимум орг-структуры, а универсального — нет.

Уточняю на вопрос «совсем ли он ничего не проектирует». В минимальном объеме, который только с уровня высокой теории можно назвать проектированием: «Я нашел, что в системе A атрибут X соответствует атрибуту Y в системе B! Значит, наш X нам надо будет засунуть в Y.». Формально это проектирование, но 99% работы — анализ, а 1% делается совсем тупо, так что….

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

«Нормально ли это — нагружать еще чем-то?».

Друзья! Нормально — все, что работает! Если оно действительно работает в вашем контексте, в важных для вас ограничениях и горизонтах. Сюда может включаться вопрос сложно подбора смены на рынке труда, вопрос сложности поиска людей с подходящей мотивацией именно для таких ролей, как вы нарезали, масса других вопросов. Но если у вас с этим все ок, т.е. решение работает — то какое может быть еще «не нормально», которое вас беспокоит?

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

Если когда-то соберусь-таки сделать курс «Мышление архитектора», то это прям будет один из лейтмотивов: «Прекратите мыслить правилами!».

Как образуются «разновидности» архитекторов

Зашел разговор о том, что казалось бы устоявшуюся в рынке «тройку» Software Acrhitect / Solution Acrhitect / Enterprise Architect никак нельзя считать основанной на «трех видах архитектуры». Это никакие не «виды архитектуры», а просто так оказывается удобно нарезать области ответственности в крупной организации за принятие технических решений разного характера и масштаба. Причем на поверку оказывается, что даже при однаковости названий этих ролей реальная ответственность в организацииях порезана сильно по-разному., так что общей карты даже и не составить. Например, «функциональные архитекторы» в одной организации напоминают «доменных архитекторов» в другой организации, но все же отличаются тем, входит ли в область ответственности решения уровня инфраструктуры.

Если пытаться искать что-то реально устойчивое, то мы найдем скорее не роли, и даже не какие-то хаарктерные предметы/области ответственности, а скорее линии потенциального разреза, по которым разные компании частенько проводят границы. При этом линий этих довольно много, и если порезать по всем этим линиям — получится абсурдно мелко, поэтому каждая компания определяет свой орг-дизайн (а роли — это про орг-дизайн), выбирая какие-то из этих линий, причем на разных уровнях и в разных орг-единицах — набор выбранных линиц разреза может быть совершенно разный и это нормально. Само же (статистическое) существование этих линий гоорит нам о потенциале, о том, что связи поперек этой линии достаточно слабы, так что по ней резать «ну в принципе можно». А вот, например, резать по признаку «фаза ЖЦ клиента» не стоит.

Навскидку описал коротко эти «базовые типовые линии разделения ответственностей, формирующие типовые паттерны ролей архитекторов»:

  • Деление «по масштабу«. Оно же стратегия/тактика. Кто-то думает за крупное, кто-то — за части.
  • Деление «по бизнесу» — если мы с т.з. системной организации бизнеса видим уже разделенные (по многочисленным возможным бизнес-причинам (из-за функциональной структуры деятельности, масштаба, территориальности, законодательства, истории слияний/поглощений, и т.п.) бизнес-функции или орг-единицы, то это может быть удобная линия разреза для ответственности в ИТ и ролей архитекторов
  • Деление «по изменениям» — если идет параллельно несколько проектов изменений, то, хотя это не статические образования, но они достаточно долгие, чтобы за их целостностью нужно было следить и одновременно удерживать scope от расширения (PM), и техническую полноту и реализуемость WBS (architect). Так рождается project/programme/solution architect как роль.
  • Деление «по доменам» и поддоменам. Даже в рамках общей орг-структуры можно выделить какие-то поддомены и группы бизнес-функциональности, между которыми слабые связи и свои жаргоны и ubiquity-языки (DDD). Можно делить. Доменный архитектор получается.
  • Деление «по техническим системам«. Вот если у нас уже есть несколько технических систем (например включая и софт и инфраструктуру), то дальнейшее ведение их ЖЦ может быть областью ответственности.
  • Классическое деление «бизнес»/»ИТ». «Бизнес» тут — это устройство организационной системы, использующей ИТ. Оно аж в язык вошло. По этой линии можно резать.
  • Можно взять и поделить софт по линии «функциональность/устройство» (черный/прозрачный ящик). Про это было много копий сломано, но вообще так можно, если и там и там много сложности набирается.
  • Можно поделить по линии «свой софт/готовая инфраструктура«. Потому что софт мы проектируем от паттернов и есть много свободы и нужно не переусложнить. А в инфраструктуре мы работаем от того, что есть на рынке и надо знать рынок и свойства готовых продуктов. Четко видная линия разреза.
  • Можно делить по viewpoint’ам (аспектам). Но тут традиционно некоторые хорошо выделяются (security, compliance), в которых много регуляции и вообще стандартных проблем-решений, а другие — хуже (performance??? reliability??? сомневаюсь), в которых больше уникальности и больше связей с уникальной функциональностью, и поэтому хуже отделяется. Рынок подсказывает наличием спец-инструментов и специалистов и аутсорсинга по тому же security и secure SDLC.
  • Можно делить по видам базовых технологий/платформ, но только если мы в технике тоже можем провести границу со слабыми связями. Например backend-frontend. Или database можно отделить, если там сложно (Oracle) и граница четкая. AWS/OnPremise. Java/.NET.

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

Ну вот и получается, что названные типичные паттерны ограничены/сформированы/оформлены несколькими из этих «потенциальных линий разреза».

  • «Enterprise Architect» — в ответственности «все предприятие», при этом с тремя опциями по линиям «IT/орг-механизмы/бизнес-модель»
  • «Solution Architect» — в ответственности «одна инициатива изменения», иногда включая орг-механизмы, иногда — только IT.
  • «Software Architect» — в ответственности отдельная программная техническая система и без инфраструктуры, иногда (все чаще) с указанием экосистемы разработки.

Это не «виды архитектуры», а паттерны нарезки ответственностей (=> ролей и должностей).

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

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

  • укрупнение организаций (Сбер Всё, так что нужно как-то биться по дивизионам, направлениям, филиалам, дочкам, и т.п.)
  • усложнение функциональное (нужно делать более крутые штуки) и по показателям качества (терабайты данных, миллионы юзеров, глобальность, гарантии надежности, etc)
  • усложнение технологическое (много новых технологий появляется и закрепляется, объем того, чем нужно владеть в сумме чтобы реализовать хоть что-то — растет)
  • снижение возраста и уровня общих компетенций в IT (меньше влезает в голову одному человеку, и он хуже понимает/держит много уровней и аспектов)
  • появление новых инфраструктур и относительно замкнутых экосистем, которые имеют свои «языки» и т.о. формируют границы. (архитектор AWS != архитектор GCP/Azure, Software Architect Java != Software Architect .NET)

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

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

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

Ну, и надо всегда помнить, что за любое разделение ролей придется платить — дорогой коммуникацией и координацией. Поэтому делить надо тогда, когда по каким-то причинам уже нельзя не делить.

Чек-лист микросервисной архитектуры

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


  1. Приложение состоит из нескольких четко идентифицированных сервисов, разрабатываемых отдельно, и работающих в разных процессах ОС.
  2. Все сервисы имеют ограниченный размер и сложность, позволяющие без слишком неприятных затрат и рисков любой одиночный сервис выкинуть и переписать заново, и удерживать сложность любого сервиса в одной средней голове.
  3. Сервисы построены вокруг тесно связанных моделей в ограниченном контексте (DDD bounded contexts), а иногда делятся дополнительно под давлением НФТ.
  4. Сервисы разворачиваются в контейнерах под управлением контейнерной системы оркестрации.
  5. Образ сервиса содержит все зависимости и не требует специальной (зависящей от сервиса) подготовки хоста.
  6. Сервисы взаимодействуют друг с другом через протоколы, не зависящие от технологии реализации сервисов.
  7. Сервисы могут быть написаны на нескольких различных технологических стеках.
  8. Сервисы могут иметь свою БД, но не имеют прямого доступа к БД других сервисов.
  9. Для взаимодействия сервисов активно используется асинхронный обмен сообщениями (messaging).
  10. Кроме системы оркестрации для работы с сервисами создана, поддерживается и развивается отдельной командой развитая (как внутренний продукт) инфраструктурная платформа микросервисов, обеспечивающая их разработку, развертывание (CI/CD), исполнение и управление (мониторинг, диагностика, и т. п.).
  11. Инфраструктурная платформа разрабатывается с применением практик Infrastructure as a Code.
  12. Создание нового сервиса и его интеграция с другими по синхронным/асинхронным каналам — дешевая автоматизированная в платформе операция (< 1 ч*ч), не требующая участия кого-либо, кроме прикладного программиста.
  13. Для всех сервисов на уровне платформы обеспечено обнаружение зависимостей, т.к что сервису нужно знать только логическое имя другого сервиса.
  14. Разрешением зависимостей можно управлять в runtime, отделяя части трафика по признакам на отдельные экземпляры (QoS), или пропуская через промежуточные прокси-сервисы.
  15. Для всех сервисов на уровне платформы обеспечено централизованное унифицированное журналирование, не требующее работы специалистов при добавлении нового сервиса.
  16. Для всех сервисов на уровне платформы обеспечено централизованное унифицированное конфигурирование, не требующее работы специалистов при добавлении нового сервиса.
  17. Для всех сервисов на уровне платформы обеспечен централизованный унифицированный мониторинг доступности и здоровья, не требующее работы специалистов при добавлении нового сервиса.
  18. Для всех сервисов на уровне платформы обеспечен централизованный унифицированный мониторинг, сбор и анализ технических и бизнес-метрик, включая производительность, не требующее работы специалистов при добавлении нового сервиса.
  19. Прикладной программист может самостоятельно, дешево и просто добавить атрибут в журнал, по которому будет возможен поиск и метрику, по которой возможно создание графиков и алертов.
  20. Обеспечена отладочная/диагностическая трассировка вызовов от входа через все синхронно вызываемые сервисы до БД включительно.
  21. Сервисы обновляются по отдельности или малыми группами.
  22. Работает по несколько экземпляров каждого сервиса, нагрузка перераспределяется между ними.
  23. Одновременно может работать несколько разных (близких) версий сервиса.
  24. Сервисы сами обновляют необходимые им структуры данных.
  25. Не используется никаких распределенных транзакций, вместо них — саги, eventual consistency, идемпотентные операции, протоколы отката и т. п. паттерны.
  26. Сервисы тестируются по отдельности.
  27. Обновления системы проходят с нулевым простоем.
  28. Сбой отдельного узла не оказывает значимого влияния на функционирование и доступность системы (практика chaos monkey).
  29. В случае сбоя сервис быстро останавливается (а не виснет) и система оркестрации его перезапускает.
  30. Для тестирования сервиса может быть собрана группа сервисов из одной (или нескольких одноименных) ветки-на-фичу (feature branch).
  31. Отдельные стенды для тестирования/демонстрации системы или фрагмента системы из нескольких сервисов создаются платформой быстро, дешево, и без участия специалистов.
  32. Перенос нужных версий БД с одного стенда на другой производится быстро, дешево, и без участия специалистов, местами — автоматически с зачисткой чувствительных данных.
  33. Обновления сервисов и инфраструктуры описано кодом и корректность этих кодов обновления автоматически тестируется на тестовых стендах (в delivery pipeline).
  34. Для сервисов проводятся автоматические тесты на соблюдение контракта платформы.
  35. Для сервисов автоматически строится фактическая диаграмма взаимодействия.
  36. Для всех сервисов есть гарантированно точные описания интерфейсов (REST, Events) и контрактов (JSON schema, etc), обновляемые не вручную отдельно, а как неизбежная часть цикла разработки.
  37. Для каждого поддерживаемого технологического стека заготовлен проект-стартер, позволяющий создать болванку корректно работающего сервиса, не делающего ничего, за 5 минут.
  38. Новая команда может подключиться к разработке нового сервиса за один день, прогнать через тесты и выпустить его на PROD.
  39. Canary releases. Для новых версий сервисов разворачивается небольшое число экземпляров, автоматически контролируется успешность вызовов к ним и при наличии большого числа ошибок или выходов за SLA версия откатывается и автоматически ставится дефект.
  40. Для сервисов определены и контролируются автоматически контракты НФТ — производительность (задержка, пропускная способность), ресурсоемкость.
  41. Сервисы активно используют паттерны для обработки отказов смежных сервисов — fallback, повторы вызовов, таймауты, и т. п.
  42. Сервисы толерантны к незначительным изменениям форматов своих зависимостей (добавление атрибутов и т. п.).
  43. Все сервисы могут работать в тестовом режиме, когда отдельные зависимости не требуются и заменяются встроенными заглушками c тестовыми данными.
  44. На уровне платформы есть механизмы контроля содержимого всех входящих/исходящих запросов и сообщений для любого сервиса.
  45. Количество экземпляров сервиса может автоматически меняться в зависимости от нагрузки.
  46. Количество хостов кластера системы оркестрации может автоматически меняться в зависимости от нагрузки.
  47. Для отдельных экземпляров или для сервиса в целом можно во время выполнения менять конфигурационные параметры (например, менять детализацию журналирования) и выдавать команды обслуживания (например, сбрасывать кеши).
  48. Платформа предоставляет готовые библиотеки/средства для решения типичных задач взаимодействия сервисов (транзакции-саги, передача реплик данных, автоматическое создание очередей, и т. п.).
  49. В любой момент времени у каждого сервиса есть одна небольшая команда-владелец, отвечающая за него включая PROD (хотя могут быть изменения и от других команд и выделенная служба эксплуатации 1-2 линии).
  50. Клиентские приложения также модульны (micro frontends) и на них распространяется большинство вышеперечисленных принципов и требований.

 

Про системное мышление

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

В очередной раз отвечая на вопрос о том, «ну что же такое это системное мышление» я вздохнул и написал это:

> (собеседник)… Хотя… пока термин (системное мышление) не раскрыт, судить о его смысле, не верно….

Давайте раскроем конкретнее, выпукло и поэтично. Хорошо освоенное системное мышление — это когда вы: быстро (в «реальном времени», в середине разговора, на грани осознавания, как обычно водите машину, но при необходимости осознавая на 95%) очень многие попадающиеся вам ситуации и вещи раскладываете по характерной мета-модели, в которой есть связанная группа понятий: система (подсистема, надсистема, целевая/обеспечивающая система), роль=функция, элемент/функциональный компонент, материал=морфология, стейкхолдер/интерес, модель/описание/вид/точка зрения, производственный/эксплуатационный контекст, потребность/требование/решение/архитектура/дизайн, функция/процесс/слой, структура/состав, связь/отношение, паттерн/стиль/архетип, понятие/знак/значение/термин, обязанность/ответственность; бегло (также на скорости речи) перемещаетесь между системными уровнями, между позициями стейкхолдеров, между точками зрения; за счет этого можете свои интуитивные «чуйки» (которые у вас были всегда) обосновать рационально, быстро протянув цепочку следствий и влияний от внутреннего технического решения до интересов стейкхолдера; проще можете «продать» идею, понимая позицию стейкхолдера; мыслите примерно одинаково системно и «железные» технические системы, и программные, и организационные, потому что в этой метамодели нет разницы; отказываетесь от любых правил, best practice, и догматов («Scrum велит делать так!») и переходите к механизмам и ситуациям, причинам и следствиям в данном конкретном окружении; начинаете требовать рациональных объяснений от других, не удовлетворяясь скрижалями и авторитетами; обнаруживаете, что многие «методологии» (от SOLID и DDD до Теории Ограничений и TOGAF) суть ограниченные и иногда ущербные частные примеры общих принципов системного подхода; легче определяете любую деятельность как целенаправленную или механистичную/догматичную; отказываетесь от многих ритуалов, не встраивающихся в цепочку системных причин и следствий до ваших интересов; легче принимаете те ритуалы, которые встраиваются в ваши интересы, даже будучи в остальном бессмысленными :), начинаете различать проблемы и задачи, реальные цели и модные лозунги, проблемы в компетенциях/личности и в организации; лучше предвидите проблемы, вызванные недостатками организации; легче отказываетесь от «стандартов», не несущих пользы, лучше видите ход мысли других людей и лучше можете его направлять, подбрасывая в реальном времени новые схемы и понятия; понимаете системное устройство коммуникации и за счет этого спокойнее и быстрее договариваетесь или рационально переубеждаете; можете объяснить по шагам, как и для чего вы делаете все вышеперечисленное и почему это наилучшее с вашей стороны действие в данный момент в данной ситуации.

Сегодня мне это видится как-то так 🙂

Про «хороший» аудит

Иногда про архитектурный/процессный аудит отзываются пренебрежительно, упирая на то, что всё, что заказчик получает в результате — это «толстенький отчет и презентацию».  Я хочу с этим поспорить, естественно, в предположении, что аудит проводится хорошо. Соответственно, мне придется рассказать, что такое хороший аудит в моем понимании, и как он проходит.

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

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

Кроме того, наличие фокусировки (вместе с пониманием предметной области и класса/масштаба рассматриваемых ИТ-систем и организации) позволяет точнее подобрать состав команды аудиторов.

Стратегия — это искусство концентрации ресурсов, и готовность отказаться от малого для достижения большего. Отсутствие фокусировки в аудите подобно отсутствию стратегии и ведет к бесполезному распылению ресурсов. Это как выстроить солдат широкой шеренгой вдоль всей линии фронта — ни наступить, ни защититься.

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

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

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

Обычно заказчик, даже планируя вложиться в аудит, всегда очень обеспокоен тем, как много рабочего времени это потребует от его сотрудников. Типичный случай — когда аудит затевается без изменения жестких проектных и программных сроков. Поэтому этап работы «только над документами» может быть полезен и как экономное средство быстро погрузить аудиторов в этот удивительный новый мир.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

В моем примере «хорошего аудита» к моменту второго приезда аудиторов (в меньшем составе) команда заказчика уже успела самостоятельно приступить к решению наиболее острых проблем.

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

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

Про орг-методологические сессии

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

1. Тема и вид сессии

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

Что это может быть?

  1. Совместно с коллективом решить какую-то уже выделенную проблему в устройстве организации/подразделения. Тогда это будет сессия проектирования. Чтобы ее проводить нужно четкое вИдение руководителя, в чем проблема. Коллектив, если эта проблема в целом в поле его понимания и компетенции может помочь найти оптимальное решение, учитывающее все факторы, и не бьющее по кому-то из них. От руководителя на старте потребуется предъявить проблему. На выходе в идеале – тезисное описание принципиального решения.
  2. Найти заранее неизвестные проблемы в устройстве, которые компании/подразделению мешают развиваться. Это полезно, если руководитель недостаточно хорошо представляет, что происходит в производстве, готов согласиться с тем, что не видит всей картины. Коллектив, который погружен в контекст более глубоко, и живет в нем – может помочь выявить гипотезы проблем. Но от руководителя здесь требуется вводная – почему компании совершенно необходимо развитие подразделения, и какие атрибуты качества/производительности/эффективности должны быть улучшены. Такую сессию можно назвать сессией проблематизации. На выходе в идеале – перечень проблем, которые нужно разрешить для осуществления шага развития подразделения.
  3. «Посадить на людей» какое-то уже известное решение, известное запланированное организационное изменение, попутно проверив его на разумность, прочность, доработанность. От руководителя требуется понимание целей и причин орг-изменения, уверенность в принципиальной правильности решения. Тогда это будет сессия организационного планирования. На выходе в идеале – понимание людей, кто какую позицию займет «с понедельника», готовность к этому, снятое сопротивление, понимание причин и необходимости.
  4. Определить направление развития организации/подразделения в условиях сложной, динамично меняющейся окружающей обстановки. Тогда это будет сессией стратегического планирования или форсайт-сессией. Тут уже от участников требуется достаточно высокий уровень подготовки и способность говорить о стратегическом уровне, не скатываясь в операционку, а также – достаточно объемные представления об окружающем компанию рыночном пространстве. На выходе в идеале –образ будущего компании, ее места и стратегии, учитывающие действия конкурентов и тренды отрасли.

В начале ведущий-методолог и руководитель-заказчик составляют что-то типа «ТЗ» на мероприятие. В чем ситуация, какие цели видим, что хотим получить, в каком режиме работаем, какой примерно состав участников, какое деление на группы (микрокоманды по 2..9 человек), какие возможны способы мотивации.

2. Возможные дополнительные результаты

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

3. Сложности и риски

В любом случае нужно понимать, что все подобные мероприятия сопряжены с некоторыми рисками и могут а) не дать желаемого результата, б) иметь и негативные последствия. С «а» все понятно – может просто ничего не получиться, а какое может быть «б»?

  1. Если результат будет маленьким или неочевидным для людей – их мотивация и уверенность в руководстве и будущем компании может снизиться: «сами ничего решить не могут, позвали какого-то урода, который тоже помочь не может, от любимой работы оторвали, тратят наше общее время-деньги на фигню, видимо компании скоро крындец». И все такое, вплоть до заявления об увольнении у особо резких.
  2. Даже если результат есть, и кто-то из участников тоже это видит, всегда найдутся недовольные – или ходом процесса, или поведением руководства, или результатами, или предстоящими переменами.
  3. Если ход процесса будет жарким, то могут возникнуть новые или усилиться старые конфликтные отношения и разногласия.
  4. … и еще много-много того, о чем мы сейчас даже подумать не в состоянии.

4. Формат организации

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

  • Установочный доклад руководителя о ситуации и целях
    (предварительно проговаривается с ведущим-методологом и проверяется на соответствие тому, что фиксировали в ТЗ)
  • Установочный доклад методолога-ведущего
    (о требуемом способе групповой работы, регламенте и необходимом по форме и содержанию результате)
  • Групповая работа в микро-коллективах (может быть полезен руководитель группы и/или игротехник)
  • Совместное (пленарное) заседание – доклады групп и коллективная дискуссия по ним
  • Методологическая консультация (прояснение понятий, введение схем)
  • Финальная рефлексия всех участников
  • Письменная рефлексия участников после мероприятия
  • Очное обсуждение результатов руководителем и ведущим-методологом

5. Роль ведущего-методолога

Ведущий-методолог обеспечивает:

  • Разработку сценария и структуры групп
  • Организацию работы в соответствии со сценарием
  • Мотивацию и направление мышления участников на целевые результаты
  • Интерпретацию полученного результата и его качества, конструктивную критику
  • Подбрасывание понятий и приемов для мышления и схематизации
  • Управление дискуссией и ее стилем, фокусировкой, атмосферой
  • Разрешение простых конфликтов, переведение их с личностной на предметную плоскость
  • Рефлексию и обратную связь участникам о происходящем
  • Информирование об источниках для самообразования

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

6. Примерный сценарий в варианте «2 раза по полдня»

Масштаб мероприятия может быть от минимального однодневного до двух, трех, или даже пяти дней с выездом за город и полным погружением. Чем длиннее и полнее погружение, тем более глубокие вещи удается вскрыть, больше ментальных барьеров преодолеть, больше материала наработать. Но и люди устают сильнее, и стоит, очевидно дороже. А результат все равно никогда не гарантирован.
Минимальный масштаб точно неизвестен, но можно попробовать «2 раза по полдня», предполагая также промежуточную работу групп между этими двумя днями и финализирующую работу групп по завершению мероприятия.

День 0

Ведущий-методолог и руководитель составляют ТЗ, договариваются о целях, форматах, сценарии мероприятия, тезисах установочного доклада руководителя. Примерная длительность очной встречи: 2 часа.

День 1

15:00-16:00       – общее заседание, открывает руководитель, представление ведущего-методолога. Установочный доклад руководителя о ситуации и целях мероприятия. Установочный доклад ведущего-методолога. Выдача задания на работу в группах.

16:00-18:00       – работа в группах.

(15 минут кофе-брейк)

18:00-20:00       – общее заседание, доклады групп, дискуссия.

День 2

15:00                   – короткое установочное сообщение ведущего-методолога.

15:00-18:00        – работа в группах.

(15 минут кофе-брейк)

18:00-20:00       – общее заседание, доклады групп, дискуссия.

20:00-20:30        – рефлексия участников, заканчивая руководителем и ведущим-методологом, выдача задания на фиксацию результатов.

7. Подготовка помещений, оборудования, реквизита, персонала

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

Проектор или большой телевизор (для мероприятий побольше, когда участники готовят презентации), несколько комплектов флипчарт-бумага-маркеры (по 1 на группу). Малярный скотч (вешать листы на стену). Блокноты или бумага А4, ручки.

Видео или аудио-запись общих заседаний.

Озвучка помещения (микрофоны, колонки), если народу много.

Кофе-брейки (чай, кофе, перекус).

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

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

Copyright © 2023 Igor Bespalchuk