Оценивая эти вещи, я обычно считаю, что полезно взглянуть на это через призму принципа СУХОЙ и посмотреть на дублирование в вашем проекте.
Если вы используете архитектуру, которая является более сложной, чем ваш проект, вы будете склонны видеть множество слоев, которые мало что делают, кроме того, что оборачивают другие слои и передают вызовы. Это повторяется.
Если, с другой стороны, вы используете тонкую архитектуру для сложной системы, вы можете обнаружить, что создание функциональных возможностей в одной части системы не позволяет вам повторно использовать эти функциональные возможности в другой части, что вынуждает вас писать очень похожий код повсюду. Это повторяется.
По моему опыту, если вы будете бдительны в выявлении дублирования и в постоянном рефакторинге для его устранения, структура представится вам. Скажем, например, что вы начинаете с довольно простой архитектуры, но разбиваете вещи на методы, как только их нужно использовать повторно, и разбиваете методы на классы, как только они должны использоваться другими классами. Затем вы можете в конечном итоге осознать, что ваши 13 классов Helper / Manager / Handler, которые вы написали для устранения дублирования, на самом деле выглядят так, будто они берут на себя ответственность, которую можно было бы более четко определить, если бы она перешла на уровень Service.
Может быть сложно узнать, когда это того стоит, но я думаю, что ключом к успеху в построении системы с большим количеством слоев является четкое понимание того, какие обязанности должны иметь различные уровни. Любой добавляемый вами слой должен помочь вам снизить сложность операций в слое над ним и упростить изящное объединение функций.