Эргономичная структура программ в3

June 22, 2023

Я продолжаю в режиме гамак-дривен девелопмента думать над этими проблемами.

И в рамках этого думания пошёл читать Lean Architecture, в которой среди прочего описывается и Data-Context-Interaction - штука от автора MVC. Он (автор MVC) ещё жив, by the way.

Лейтмотив книги, на мой взгляд, заключается в тезисе, что системы состоят из двух частей - what-the-system-is и what-the-system-does. Очень условно - модель данных и АПИ, внезапно. Или модель предметной области и юзкейсов.

Так же в этой книге есть ещё любопытный термин - Atomic Event Architecture. Что по сути является синонимом MVC.

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

И далее автор пишет:

In fact, the atomic event architecture has a liability in that it fattens the interfaces of the domain classes and makes them less ‘‘domainy’’ – they become hybrid homes for what-the-system-does-and-is alike.

Если вспомнить о том, что я делаю ООД на уровне модулей - это как раз то, обо что споткнулся я:

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

И в качестве ответа автор предлагает DCI. Эта штука довольно мозголомная и плохо ложится на современные языки, поэтому под неё запилили собственный. Поэтому в чистом виде себе я её точно не возьму. Но кое-какие идеи почерпнуть можно.

Наконец, в книге вводится понятие habit - переиспользуемого кусочка юзкейса:

It can be useful to compromise here and treat authentication as a use-case-like-thing, but one that is the purview of the programmer rather than that of the business folks. We call such a pseudo-use case a habit.

Всё это приводит нас к следующему.

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

И в этом случае симметрии можно будет добиться, только если ввести дополнительный уровень сложных юзкесов для всех операций, что в моём случае приведёт к целому слою классов, который будет на 90% состоять из одно-строчного делегирования. Что неэргономично.

Соответственно мне надо примириться с этой асимметрией и дать ей место в Эргономичной структуре програм.

Во-вторых, она даёт (в общем-то очевидный) ответ как декомпозировать "слой приложения" - по юзкейсам.

Соотвественно, у меня получается такой кандидат в третью версию эргономичной структуры програм:

erogonomic programs structure v3 system pattern.drawio
erogonomic programs structure v3 operation pattern.drawio

Это всё пока что чисто умозрительно и ещё только предстоит проверить как реальный код ложится на эту структуру - благо за последние несколько лет у меня появилось несколько очень разных (насколько это возможно в контексте разработки бэков на Kotlin) систем для экспериментов.

Кроме того, у этой структуры уже сейчас очевидны две проблемы.

По чисто механической метрике сцепленности/связанности (кол-во связей между и внутри модулей) в3 уступает в2 - в модулях фич связанность будет нулевая, плюс в целом в системе сцепленность будет выше. Рационализировать эту переобувку в полёте мне ещё предстоит :troll:.

И "Рациональный подход к декомпозиции систем на базе эффектов", (который я кстати переименовал в "В подход к синтезу ОО-дизайна на базе эффектов" :) ) для этой структуры, кажется не сработает. Хотя я в Проекте Э немного поупражнялся в построении декомпозиции кода сложных юз кейсов на базе диаграммы - и там тоже появились два разных вида модулей. Но, справедливости ради, я это делал не по алгоритму.