🧩 Модульная архитектура после первого десятка фреймворков неизбежно превратится в вертикальный граф зависимостей, это заблокирует возможность параллельной сборки, а также возникнет проблема невозможности взаимного импортирования фичемодулей (A.framework <-> B.framework).
Решение этих проблем кроется в создании банальной прокси для межмодульного взаимодействия
Фичемодулей, теперь они не используют друг друга напрямую, а «общаются» через технический.framework
Граф зависимостей становится плоским, гарантируется отсутствие циклических зависимостей
Неправильно: фичемодульА -> фичемодульБ
Правильно: фичемодульА -> технический.framework •••> фичемодульБ
Технический Фреймворк должен неявно (без импортирования) знать о том какие есть публичные интерфейсы и какой объект(принадлежащий более верхнеуровнему модулю) реализует его
У нас есть нечто особенное для разделения модулей по слоям, мы уходим от отдельного прокси фреймворка в сторону более гибкой схемы с разделением модуля на фреймворка «интерфейса» и «имплементации».
«Интерфейс» фреймворки не могут импортировать другие «интерфейс» фреймворки, «имплементации» свободно импортируют «интерфейсы» но не могут импортировать «имплементации»
Модуль состоит из:
Interface.framework
Implementation.framework
Mock.framework (фейк имплементация интерфейса)
Наличие моков в каждом модуле значительно упрощает тестирование и снимает головную боль по настройке моков, достаточно 1 раз сделать сетап моков модулей которые используются в модуле
Ставшая легаси objc реализация прокси раньше также загружала lazy фреймворки через dyld при первом обращении к модулю. Перфоманс стал намного лучше, когда мы перешли на статическую линковку.
На сегодняшний день улучшеная реализация легаси прокси имеет минимальный оверхед в рантайме, все что возможно предрассчитывается и подставляется кодгеном
Миша Харитончик