Привет!
Кажется у меня по мотивам Проекта Э на горизонте замаячил очередной кризис Эргономичного подхода.
При том зашатались одновременно два столпа - декомпозиция на базе эффектов и функциональная архитектура.
С декомпозицией на базе эффектов в одном из модулей начала стрелять одна из проблем Труъ ООП. Он начал обрастать слишком большим количеством операций, предназначенных для разных ролей и юз кейсов.
Кроме того, я ещё раньше стал замечать, что зачастую в модуле появляется зависимость только из-за того, что операция сильно сцепленная с состоянием модуля должна потрогать состояние соседнего модуля. Это, в принципе можно обойти с помощью событий, но они вносят дополнительную сложность в систему и снижают эргономичность кодовой базы.
Эту проблему можно попробовать решить вернувшись к версии Эргономичной структуры программ 1.5-летней давности с разбиением слоя домена (состояния) и приложения (операций). Однако этот пост заканчивается словами "Что значит "проектируйте слой ядра приложения"? Вот у вас есть требования, вам надо спроектировать ядро - как это сделать? Ответ в следующем посте.".
В итоге ответ появился через 1.5 года в виде объединения этих слоёв и тут же зашатался.
Я отказался от изначальной идеи разделения по двум причинам:
1. при таком подходе отсутствует сокрытие информации. Как следствие появляются все проблемы процедурного программирования - потенциальная возможность порчи состояния, и распространение изменений в структурах данных домена на слой приложения
2. я не смог найти вменяемого способа декомпозировать слой приложения.
Для проблемы с защитой состояния у меня, возможно, изначально была основа решения - неизменяемые агрегаты и гайдлайн, что операции модификации агрегатов должны быть около самого агрегата. Но сейчас на практике это не жёсткий гайдлайн и код модификации утекает в слой операций. Это возможно потому, что у меня агрегаты являются Kotlin Data классами, у которых есть метод copy, который позволяет сделать с объектом что угодно. И если эти дыры прикрыть - убрать возможность создавать произвольные вне слоя домена, то это позволит мне защитить состояние агрегата.
Ту же идею можно приминить и к защите слоя приложения от изменения структуры данных слоя домена. Для этого надо будет запретить обращаться к данным агрегатов и предоставить более высокоуровневое АПИ для их считывания.
Тут мы опять можем прийти к проблеме разрастания поведения, но:
1. она в целом будет уже на меньшем масштабе
2. методы работы с агрегатом можно будет группировать в подмодули.
В общем план как решить проблему отсутствия сокрытия информации у меня есть.
А вот как декомозировать слой приложения - я пока не знаю. Пойду курить мат часть со всех возможных сторон - перечитаю Structured Design, Object-Oriented Software Engineering, Applaying UML and Patterns, Domain Modelling Made Functional, дочитаю Functional Design and Architecture и Functional and Reactive Domain Modeling. Надеюсь что-нибудь придумаю.
Касательно функциональной архитектуры проблема меньше. Точнее я вообще не уверен, что проблема есть.
Я люблю симметрию и регулярность в коде. И моему чувству прекрасного хочется что ROP-ые операции у меня оркестировали более низкоуровневыми процедурами чтения и записи данных и функциями трансформации данных.
Однако на практике у меня некоторые операции ещё и другие операции дёргают. И мне это кажется нарушением принципа одного уровня абстракции.
Но я пока не могу сформулировать к каким систематическим проблемам это ведёт.
Поэтому я поищу ответ и на этот вопрос в тех же книгах, но если ничего не найду - может и дальше поживу с этим.
А как ваша ночь прошла? 😂
#ergo_approach@ergonomic_code
Post #326
571