Смешение уровней абстракции закладывает бомбу в основание вашего проекта
За годы работы архитектором я видел разных заказчиков, и одна из самых частых ошибок формулирования ТЗ и хотелок заказчика — это смешение разных уровней абстракции. Приходит человек и говорит:
— Мне нужна железка, которая будет управлять приводом дверей, и показывать на семисегментном экране текущее состояние, и обязательно с внешним сервером для удаленного управления, чтобы по TCP общалось с этим сервером, а для панели управления взять VueJS.
Вроде, понятно, что человек хочет. У кого-то даже такое ТЗ вызывает энтузиазм — человек, казалось бы, четко понимает, чего хочет. Зачастую он даже указывает на конкретные контроллеры/компоненты/фреймверки/протоколы.
И по такому заказу, безусловно, можно сделать нужную железку. И она даже будет работать, если подобранные компоненты не противоречат друг другу. Но если расчет идет не на проект, а на продукт, и его потом необходимо будет поддерживать, то гораздо полезнее потратить время и аккуратно разделить эти хотелки по уровням, понять, зачем именно такой экран, почему TCP, и причем тут VueJS. Вполне может оказаться, что это технологии, к которым заказчик испытывает приятные чувства из-за синдрома утенка. Или он просто не знает, что есть и другие типы экранов.
В данном случае, мы сначала говорим о первом уровне:
Устройство, управляющее приводом, с индикацией и удаленным управлением.
Потом начинаем конкретизировать требования (но не конкретные технологии):
Устройство в корпусе IP68, с питанием 230в, управляющее асинхронным приводом мощностью 800вт через частотный привод по modbus, имеющее хорошо различимый индикатор, четыре состояния которого (открыто/закрыто/в процессе/поломка) должен распознавать человек с 10 метров, имеющее удаленное управление, доступное из современных браузеров через интернет.
И только после этого можно начать подбирать под требования уровень реализации. Вот такой контроллер, вот такой rs485-трансивер, вот такой блок питания, вот такой индикатор.
Разделить эти два уровня (требований и реализации) просто — в большинстве случаев под одни и те же требования можно подобрать разные реализации, и это никак не изменит уровень требований. Уровень требований может меняться из-за того, что реализация слишком сложная дорогая, или не нравится визуально, но он не должен меняться из-за выбора контроллера, более удобного разработчику, иначе вы слишком глубоко заглянули в требованиях или просто поленились узнать, почему было сформулировано такое требование.
Скажем, заказчик хочет экран с символами по 8 сантиметров. В этот момент архитектор или руководитель продукта должен поинтересоваться, а почему именно 8 сантиметров? В большинстве случаев оказывается, что у заказчика внутри есть требование «видимость с 10 метров», но он решил упростить задачу и высказал сразу конкретное требование. Или просто не может взглянуть абстрактно, потому что мыслит о проекте в более понятных ему объектах: абстрактное «экран, видимый с 10 метров» это сложнее, чем «большой, ну, знаешь, такой дисплей из сегментов, в коробке, я вот сюда его на стену повешу».
Но заказчик по определению не обладает компетенцией по разработке проектов, иначе бы он не пришел к вам. И даже если он этими компетенциями обладает — он их не может применять в разработке этого конкретного проекта, потому что зачем он тогда пришел к вам?
Принимать решения в проектах должен тот, кто будет нести за них ответственность. Если заказчик не будет нести ответственность за сроки разработки кода для определенного экрана, который он выбрал, то он не должен выбирать этот экран. Задача заказчика — сказать, какие требования, по его мнению, реализует выбранная им модель экрана.
Задача человека, принимающего архитектурные решения — выбрать наиболее подходящее решение для реализации этих требований. Это может быть и светодиодный экран, и ЖК, и просто светофор из 4 цветов, и табло с наклеенными надписями.
Но архитектор не должен принимать все, что скажет заказчик, как данность: если бы таким образом можно было составить ТЗ, достаточное для разработки, то заказчику не нужны были бы посредники между ним и разработкой.
Описание требований не на том уровне архитектуры, к которому они относятся — опасная вещь, гарантированная хоронящая архитектуру проекта, низводя ее даже не до описания хотелок, а до опасной смеси газов, безопасных по одиночке, но готовых взорваться при смешивании. И реализованная по этой архитектуре система рано или поздно рванет — текущими абстракциями, сложной доработкой или падающими костылями при любом изменении функционала.
Представьте, что вы строите дом. Базовый элемент дома — кирпич. Вы не можете купить пол-кирпича, но купив пять самосвалов кирпичей, вы не купите дом. И даже сто кирпичей не превращаются в стенку. Для постройки, на самом низком уровне вам придется оперировать именно одним кирпичем, не больше и не меньше.
Но проектировать дом в кирпичах, и даже в конгломератах кирпичей — это очень плохая идея.
Во-первых, вырастает сложность. Любая память и ресурсы конечны, и лучше потратить их меньше, чем больше. Дом, в котором описано местонахождение каждого кирпича слишком сложен для восприятия, состоит из слишком многих элементов. Его трудно рисовать (вместо быстрого рисунка отдельных комнат мы вырисовываем каждый кирпич), чертежи трудно читать, 3D-модели долго рендерятся, закупочные ведомости оперируют точным количеством кирпичей вместо тонн.
Во-вторых, теряется гибкость: сдвиг одного кирпича — это уже ошибка. Мы не даем пространства для маневра на низком уровне разработки, что заставляет нас делать чужую работу, и получать сообщения о ошибках, которые нам не критичны. Если мы ставим задачу как «сделать стену из кирпичей толщиной в 30 сантиметров», то у строителя есть возможность класть кирпичи, как ему хочется, пока это не нарушает прочность или другие ограничения. Если мы даем ему точный чертеж расположения кирпичей, то при следующей проверке накопленная разница в толщина шва в пару миллиметров даст нам ошибку в пол-сантиметра в расположении конкретного кирпича, что приведет к несоответствию стены и ее ТЗ. Иногда это ошибка, но в большинство случаев неправильное положение одного кирпича ни на что не влияет, и продиктовано обстоятельствами, которые мы при проектировании учесть не могли: например, некорректные размеры кирпичей с производства. Можно вернуть, можно построить из таких, это будет проще и дешевле. Проектирование на уровне отдельных кирпичей лишает нас этого выбора, заставляя либо соответствовать идеальному результату, либо выкидывать всю работу.
В-третьих, мы не можем перейти на другой уровень, начать думать о комнатах, пока у нас есть только бесконечно перетекающие друг в друга конгломераты кирпичей и какие-то пространства между ними. Кирпичи для нас важнее пространства между ними, оно лишь отсутствие кирпичей, а не место для жизни. Вроде, дом строится ради комнат, но каждое желание изменить стену в комнате настолько сложно, приводит к настолько большому количеству операций по перемещению кирпичей и выстраиванию нового порядка кладки, что мы почти перестаем это делать: проще согласиться с неудобной стенкой, чем постоянно перемещать кирпичи туда-сюда на плане.
В-четвертых, невыносима идея о замене базового элемента. Все построено на кирпичах, вы считаете расстояния в кирпичах, вы считаете стоимость в кирпичах, вы считаете вес в кирпичах, вы считаете теплопроводность стенки в кирпичах. Это удобно, так как не создает лишних единиц измерения, лишних абстракций. Теплопроводность в кирпичах легко переводится в расстояние, а стоимость легко выводится из расстояния.
Но за дом из других материалов браться невозможно: придется прекратить ориентироваться на кирпичи, а это рушит всю картину мира. Хотя, при правильном разделении слоев абстракции вы прекрасно спроектируете комнаты в метрах, посчитав стоимость в рублях, нагрузку на сваи в тоннах, проведете расчет теплопроводности в Вт/(м·K), и только на последнем уровне проектирования решите, что же взять — кирпичи, газобетон или бетонные панели. А если заказчику не понравится решение, поменяете его, не трогая весь остальной проект.
Работа над архитектурой — это хождение по уровням абстракции. Виденье этих уровней — это свойство, необходимое для хорошего архитектора.