Pull to refresh

Монолитная система VS множество самостоятельных модулей на примере притчи о слоне и мудрецах

Reading time4 min
Views5.1K
Данная статья представляет собой в основном вольный пересказ фрагмента книги Эрика Эванса «Предметно-ориентированное проектирование», в котором он рассуждает о Separate Ways и Bounded Context.

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




Здесь слон – сложная предметная область, а мудрецы – программисты.

Шесть седовласых мудрецов
Сошлись из разных стран.
К несчастью, каждый был незряч,
Зато умом блистал.
Они исследовать слона
Явились в Индостан.
Один погладил бок слона.
Довольный тем сполна,
Сказал он: «Истина теперь
Как божий день видна:
Предмет, что мы зовем слоном, ­
Отвесная стена!»
А третий хобот в руки взял
И закричал: «Друзья!
Гораздо проще наш вопрос,
Уверен в этом я!
Сей слон — живое существо,
А именно змея!»
Мудрец четвертый обхватил
Одну из ног слона
И важно молвил: «Это ствол,
Картина мне ясна!
Слон — дерево, что зацветет,
Когда придет весна!»
Тем временем шестой из них
Добрался до хвоста.
И рассмеялся от того,
Как истина проста.
«Ваш слон — веревка. Если ж нет
Зашейте мне уста!»
А как известно, мудрецам
Присущ упрямый нрав.
Спор развязав, они дошли
Едва ль не до расправ.
Но правды ни один не знал,
Хотя был в чем-то прав.

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

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

Преимущества малых контекстов (множество разнородных модулей):
• снижаются издержки коммуникации между разработчиками (т.к. самих коммуникаций меньше);
• НЕПРЕРЫВНУЮ ИНТЕГРАЦИЮ (CONTINUOUS INTEGRATION) проще выполнять в ма­лых группах с небольшими базами кода;
• в больших контекстах могут потребоваться более универсальные и абстрактные модели, требующие редко встречающейся квалификации разработчиков;
• небольшие модели могут обслуживать специальные потребности или соответствовать жаргону специализированных групп пользователей, а также узкоспециаль­ных диалектов ЕДИНОГО ЯЗЫКА (UBIQUITOUS LANGUAGE).

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

P.S. Данная статья родилась как ответ на небольшой холивар в этой статье. Если интересны примеры из реальной жизни, рекомендую почитать статью Безудержное нарушение принципа многоуровневости.
Tags:
Hubs:
+2
Comments0

Articles

Change theme settings