Правило 10. Следите за терминологией
Я уже писал о важности проектирования концептуальной модели данных и негативных последствиях, когда она отсутствует.
Недавние события в моей работе подтолкнули меня расширить эту мысль.
В статье «В чем задача архитектора» одной из задач я указывал выработку общего языка.
О важности говорить на одном языке можно слышать из каждого утюга. В частности, Эрик Эванс в своей книге «Domain-Driven Design» повторяет эту мысль много раз. Эта мысль повторялась настолько часто и так неумело, что она уже стала как заезженная пластинка, которую мы слышим, но не слушаем. Говоря по-русски — пропускаем мимо ушей.
В прошлом году мне довелось принять участие в интересном эксперименте: проектирование системы регистрации и авторизации пользователей. Одну задачу поставили двум командам подрядчиков, а я должен был принять их результат и оценить, какое решение нам больше подходит.
То есть я не должен был проектировать сам, а только отвечать на вопросы команд, оценивать их результаты и, как заказчик, указывать, что мне не нравится.
Скажу сразу — так не вышло. То, что мне предстоит самому вникать в процесс проектирования, стало понятно ещё на ранних этапах проекта. Но паровоз уже было не остановить, и пришлось адаптироваться по ходу движения.
Последствия этих решений догоняют меня и в начале 2025 года. Из этой деятельности мы с коллегами вынесли два ключевых вывода:
- Отдавать ключевые компетенции (а проектирование архитектуры как раз такая) на сторону — это стрелять себе в колено.
- Не формировать общий язык терминов и понятий — это всё равно что вколоть анестезию в десну перед выходом на сцену.
О первом уроке я расскажу как-нибудь в другой раз, в другой статье. А в этот раз хочу коснуться темы общего языка.
Немного вводных о задаче, речь о которой шла выше: две независимые команды проектируют одно и то же решение и подбирают подходящий технологический стек.
Мне нужно принять результаты проектирования, сравнить их между собой и выбрать лучшее.
Проблема с общностью языка встречалась мне неоднократно в моей карьере, и я приведу несколько примеров проблемы синхронизации языка и к чему это приводило.
Итак, сложностей в согласовании общего языка было две:
- Сопоставить термины двух команд на верхнем уровне, то есть у меня в голове;
- Согласовать термины внутри каждой из команд;
I. Трудность первая - общая модель языка
Первым шагом на пути к общему языку был выбор нотации проектирования архитектуры, в нашем случае это была нотация C4. Выбрали её в силу того, что эта нотация уже была принята в нашей материнской компании, и мы не хотели тратить время на синхронизацию типов элементов и диаграмм.
Вторым шагом мы договорились, что описание реализации будет включать сценарии использования системы, при этом чётко не оговорили, в какой нотации они будут. Я мог бы задать их изначально, но в рамках эксперимента мы решили не загонять команды в какие-то жёсткие рамки.
По итогу я получил описания сценариев использования как в виде UML Sequence Flow, так и в виде BPMN диаграмм. Но это была только вершина айсберга и, честно говоря, не самая ключевая.
Для фанатов нотации C4 и прочих других фреймворков я уже писал об опасности фреймворков в другой статье и, возможно, даже посвящу отдельную статью проблеме использования C4.
Пока лишь небольшой спойлер: согласно С4, на верхнем уровне строится диаграмма контекста, которая показывает, как описываемая система вписывается в общий ландшафт. А уровне ниже(С2) система дробится на уровне контейнеров, которые, в свою очередь, состоят из компонент (уровень С3).
Но эти контейнеры, как правило, не равны понятию докер-контейнера, а если архитектура системы не микросервисная, то контейнеров там и вовсе нет. Зато есть подсистемы и компоненты, которые опять-таки не сходятся с С4.
Запутаться даже на этом поле небольшого количества понятий крайне просто. Начните обсуждать диаграмму С2 и подходы к масштабированию с использованием кубера, и довольно быстро нить разговора потеряется. Адепты С4, наверное, скажут мне, что такие вещи нужно обсуждать не на этой диаграмме, а на диаграмме развёртывания, и тогда всё станет понятно. Однако держать в голове, что тут контейнер — это одно, а вот тут совсем другое, крайне непростая задача.
А когда вам приходится читать длинный и сложный документ, помнить об этом становится ещё сложнее, и в итоге в голове образуется такая каша, что разобраться в ней не могут даже авторы документа.
Один случай из моей практики был довольно показательный. В одном телеком-операторе было несколько разных биллинговых систем, от разных поставщиков. Развивались они с разной скоростью и стоимостью, и было принято решение постепенно заменить их на одно, типовое решение.
Чтобы последующий текст был нагляднее, буду использовать следующие термины: заменяемая система, новая система.
Был выбран первый кандидат на замену, и начались работы по проектированию. Одна из сессий, на которой и произошёл знаменательный случай, была посвящена миграции данных. Две команды на первый взгляд использовали один и тот же набор понятий: Абонент, Клиент, Расчётный счёт. Я был знаком с моделью заменяемой системы, но модель новой системы изучал прямо на встрече. В какой-то момент я понял, что несмотря на одинаковое название сущностей, они имеют разную природу вещей.
В ходе разговора обнаружилось следующее: в заменяемой системе сущность Абонент содержала в себе данные человека или организации, к нему подвязывался набор заказанных услуг и ссылка на расчётный счёт, на котором собирались счета и платежи за услуги.
В новой системе существовала сущность Клиент, на которой собирались данные человека или организации. К клиенту создавался абонент, который содержал в себе номер счёта и тип оказываемых услуг (например, интернет, телевидение, телефон), а под абонентом собирались подключенные к нему услуги.
Таким образом, сущность Абонент новой системы больше была похожа на Расчётный счёт заменяемой системы, а сущность Клиент новой системы по своей природе больше была похожа на сущность Абонент заменяемой системы.
Пока мы не построили соответствующие модели и не провели сопоставления, мы говорили о разных вещах, но одними словами.
II. Трудность вторая - общность языка внутри команды
Когда в последнем проекте я составил карту понятий в своей голове и убрал откровенно лишнее разнообразие у обеих команд, я смог предметно обсуждать архитектуру обоих решений, не загоняя команды в жёсткие рамки единого языка. Весь маппинг был у меня в голове.
Когда же команды начали сдавать черновики итоговых документов, началась вторая серия брожения по мукам. Оказалось, что как члены команды А, так и члены команды Б в своих описаниях:
1. Используют разные слова для описания одного и того же явления.
Например: клиент/участник/пользователь или система/сервис/компонент.
В итоге некоторые секции документа стали выглядеть примерно так: Клиент вводит свои учётные данные в систему, сервис отправляет одноразовый код, который пользователь вводит на экранной форме, после чего попадает в личный кабинет участника.
2. Используют одно и то же понятие для описания разных явлений
Например, под клиентом имелся в виду человек, который пользуется услугами компании. Но под словом клиент также имелся в виду браузер на компьютере, через который клиент получал доступ к услугам.
Некоторые диаграммы и пояснения выглядели примерно так:Клиент, используя UI клиента, получает доступ к сервису системы, через который Клиент может просмотреть данные своих покупок. Для этого клиент отправляет GET запрос такого-то вида…
Ситуацию усугубляло то, что нигде не было терминов и определений, которые так не любят ИТ-парни, руководствуясь принципами молчания настоящего мужчины:
Что тут говорить, если и так всё ясно. Что тут говорить, если ничего не ясно.
Когда же я заставил коллег всё-таки сделать термины и определения и в этом процессе осознать модель предметной области, это не решило проблему до конца.
Несколько версий документа подряд коллеги продолжали использовать разные термины из согласованного перечня. И когда я указывал им на противоречивость написанного, они с некоторой долей стыда исправляли свои ляпы.
Многие мои коллеги-программисты говорили мне, что на этапе проектирования много словоблудия и что, когда пойдёт программирование, все объекты будут чётко описаны и в коде не повторятся. Собственно компилятор не даст вам использовать одни и те же объекты. А все словесные баталии — дело теоретиков и бюрократов.
Мой друг, который участия в этом проекте не принимал, но работает вместе со мной над общей ИТ-платформой, слушая мои беседы с командами рассказал мне классную историю из его опыта.
Он принимал участие в проекте большого внедрения нового ИТ-ландшафта в достаточно крупную компанию. И в отличие от многих других проектов, он настоял на детальном проектировании всего ландшафта, включавшем и проектирование модели предметной области.
После кучи баталий и сломанных копий, общая модель сущностей была согласована и отдана на реализацию. Маленький нюанс, который вскрылся позже, был в том, что модель была описана на русском языке и русскими терминами, никаких англицизмов.
В ней был объект, с помощью которого оператор службы клиентской поддержки фиксировал факт взаимодействия с клиентом:
- Выбирал причину взаимодействия;
- Вносил описание (дополнительные комментарии);
- Фиксировал результат
Объект назывался «Обращение» и был типовым переводом английского слова «Interaction», что словарь переводит как «Взаимодействие». Но «Взаимодействие» не прижилось, а «Обращение» стало стандартом.
Конечно, реализовать в коде «Обращение» команда разработки не могла, поэтому, недолго думая, они вбили название объекта в переводчик и получили перевод - «Appeal».
«Appeal» несёт совсем другую смысловую нагрузку. Appeal - это титул или вежливое обращение к человеку перед его именем или фамилией, будь то Sir, Miss в английском, или SAN в Японском. Более того, такое понятие в системе существовало, в качестве атрибута на объекте «Контакт».
Когда код был написан все «Interaction» в базе превратились в «Appeal».
Никто так и не признался, кто сделал такой перевод, но на различных демо модели это выглядело до забавного глупо. Ситуация была не такая критичная, как в моём случае с Абонент и Клиент, но выставила команду в дурном свете.
В качестве заключения, я привёл иллюстрацию чешкого словаря и перевод слова Девка и Дивка. Девка, как говорит Владимир Путин, это женщина с низкой социальной ответственность, а Дивка это девушка. Этот пример, ещё более показателен тем, что в Польском языке, значения ровно противоположные. Эти страны граничат друг с другом и народы часто пересекаются друг с другом.
Надеюсь, что этой статьёй я смог подчеркнуть важность общего языка, который вы используете как внутри, так и вовне команды. Отсутствие дисциплины в области языка может в лучшем случае поставить вас в комическое положение, как в случае с «Appeal», а в худшем случае привести к совсем иной реализации системы, как в случае с «Абонент» и «Клиент». А в некоторых случая, вы ещё легко можете получить по лицу за нанесённое оскорбление.