Есть старая шутка про картографа, которого попросили сделать идеально точную карту королевства. Он долго работал и в конце концов создал карту в масштабе один к одному. Она покрывала всё королевство целиком, была абсолютно точной и совершенно бесполезной. Я вспоминаю эту историю каждый раз, когда вижу техническое задание на триста страниц, в котором описано всё, кроме главного. Сложный мир нельзя понять, повторив его. Его можно понять только упростив. И вот здесь начинается искусство моделирования.
Модель это осознанное упрощение
Любая программная система это модель. Она не равна бизнесу, она его упрощённое отражение. В реальном складе есть запах картона, сквозняк из ворот, кладовщик, который знает, что верхняя полка шатается. В модели склада есть ячейки, товары, остатки и движения. Всё остальное мы сознательно отбрасываем, потому что для управления оно не нужно.
Мастерство здесь в выборе: что оставить, а что отбросить. Отбросите слишком много, и модель перестанет отражать реальность, система будет считать одно, а на складе будет другое. Оставите слишком много, и получится та самая карта в масштабе один к одному: громоздкая, дорогая и непонятная. Хорошая модель похожа на схему метро. Она не показывает реальные расстояния и изгибы тоннелей, но по ней невозможно заблудиться, потому что она показывает ровно то, что нужно пассажиру.
Модель хороша не тогда, когда в ней всё есть, а тогда, когда в ней нет ничего лишнего и есть всё необходимое.
Единственный способ понять сложное
Человеческий мозг удерживает в голове одновременно совсем немного вещей. Психологи спорят о точном числе, но все сходятся в том, что их единицы, а не сотни. А современная учётная система состоит из сотен сущностей, тысяч правил и десятков тысяч строк кода. Понять такую систему целиком невозможно. Ни мне, ни любому другому архитектору. Единственный способ с ней работать это разбить её на части, каждую из которых можно понять отдельно.
Так устроена любая сложная вещь, созданная человеком. Самолёт не проектирует один инженер: есть команда двигателя, команда крыла, команда электроники, и каждая работает со своим модулем, зная только интерфейсы, которыми он стыкуется с соседями. Город не управляется одним человеком: есть районы, службы, ведомства. Модульность это не модное слово из программирования, это способ, которым человечество вообще справляется со сложностью.
Что делает модуль хорошим
В программировании есть два принципа, которые я считаю почти законами природы. Первый: слабая связность. Модули должны как можно меньше знать друг о друге и общаться через небольшие понятные интерфейсы. Модуль продаж не должен лезть во внутренности склада, он должен попросить склад зарезервировать товар и получить ответ. Тогда склад можно переделать изнутри, и продажи этого даже не заметят.
Второй: высокая сцепленность. Всё, что относится к одной задаче, должно жить в одном модуле. Если логика расчёта скидок размазана по пяти разным местам системы, то любое изменение правил скидок превращается в охоту за этими кусочками, и один обязательно будет пропущен.
- Хороший модуль можно объяснить одним предложением: «этот модуль отвечает за складские остатки».
- Хороший модуль можно изменить, не трогая другие.
- Хороший модуль можно протестировать отдельно.
- Над хорошим модулем может работать отдельная команда, не мешая остальным.
Последний пункт особенно важен для бизнеса. Когда система модульная, команда разработки может работать параллельно: одни делают новый отчёт, другие интеграцию с доставкой, третьи переделывают права доступа, и никто не стоит в очереди за чужим кодом. Скорость развития системы растёт не потому, что люди работают быстрее, а потому, что они перестают мешать друг другу.
Где проходят границы
Самый трудный вопрос в модульности это не «нужно ли делить», а «где резать». И здесь я всегда советую смотреть не на технику, а на бизнес. Границы модулей должны повторять границы реальных областей ответственности в компании. Продажи, склад, закупки, финансы, персонал. Если в компании есть отдел, который отвечает за что-то, скорее всего, в системе должен быть модуль, который отвечает за то же самое. Тогда изменения в бизнесе естественно ложатся на изменения в одном модуле, а не расползаются по всей системе.
Ошибка, которую я вижу часто: делить систему по техническим слоям, а не по смыслу. Отдельно все экраны, отдельно вся логика, отдельно все данные. Выглядит аккуратно, но любое изменение бизнес-правила требует правки во всех трёх местах. Это как разделить оркестр не на инструменты, а на «все, кто играет громко» и «все, кто играет тихо».
Что делать завтра
Нарисуйте свою систему или ту, которую собираетесь строить, как набор блоков. Для каждого блока напишите одно предложение о том, за что он отвечает. Если предложение не получается, блок слишком большой или слишком размытый. Затем нарисуйте стрелки между блоками. Если стрелок слишком много и они идут во все стороны, модули слишком сильно связаны, и любое изменение будет болезненным.
Модульность заложена в основу всего, что мы делаем в Ingello. Forma устроена как набор модулей, каждый из которых отвечает за свою область: продажи, склад, закупки, найм, проекты. Fractal описывает систему моделями с явными связями, и границы модулей видны в описании ещё до генерации кода. А в Systems мы начинаем проектирование именно с того, чтобы найти правильные линии разреза. Сложность мира никуда не денется. Но её можно разложить по полкам так, что каждая полка станет понятной.