Комплекс доменной неполноценности — это когда веришь, что доменный слой приложения должен быть самым большим и самым важным, и винишь себя в том, что в твоём коде это не так. Это происходит, если воспринимать «Чистую архитектуру» как единственно верный способ писать код. Привет, меня зовут Саша, я Head of mobile в компании «Метр квадратный». Под катом — почему появился этот комплекс и как с ним бороться. Сразу оговорюсь, в статье много моего личного мнения, и будет круто, если в комментах вы поделитесь своим. Перенесёмся в 2009 год. Только‑только вышел Android 2.0.1, а Android‑разработка — занятие почти неизвестное. Телефоны совсем слабые, а приложения — простые и легковесные. У скромного комьюнити разработчиков есть столь же скромная документация, в которой рекомендуется держать весь код приложения в многочисленных Activity. Если какой‑то код вы вынесете в отдельный класс, это будет считаться верхом искусства ООП.  Но с 2009 года многое изменилось: часть разработчиков начали писать по канонам «Чистой архитектуры», приложения стали гигантскими, а бизнес‑логики в них стало пропорционально меньше. Пришлось отдать это «голодающим» бэкенд‑разработчикам. Конечно, можно привести примеры приложений с жирным доменным слоем (и хрустящей корочкой из юнит‑тестов), но многим из нас (и мне в том числе) чаще приходилось писать совсем другие приложения. Что‑то по ТЗ типа: «Возьми вот эти данные и покажи их вот в этом списочке». Так в чём же здесь проблема, спросите вы? Я расскажу. Умные книжки учат нас, что приложение — это бизнес‑логика. Всё остальное: UI, сеть, база данных — это всего лишь детали реализации, мелкие библиотечки, которые должны пресмыкаться перед могучим доменным слоем. На деле UseCase иногда состоят всего из пары строчек, а Entity — вообще нет. Из‑за этого получается неприлично тонкий доменный слой — стыдно показывать даже друзьям. И так повторяется из проекта в проект. Кажется, у кого угодно вырастут комплексы от такого. Я попробую копнуть в причины этого феномена, а затем будем «лечиться» от этих комплексов. Знаете, что общего у книг Роберта Мартина, Кента Бека и Мартина Фаулера? Они изобилуют примерами кода, «не замусоренного» UI‑фреймворками, получением данных с бэкенда и прочими мелкими деталями реализации.  Нам показывают код таким, каким он должен быть: пронизанным духом настоящего ООП, не зависящим ни от чего, прекрасно тестируемым, лаконично решающим задачу. Читаешь и радуешься: если я буду писать так же, то смогу иметь 100%‑е покрытие тестами, код будет независим от сторонних библиотек, а значит, доменный слой будет основой всего, а presentation‑ и data‑слои — лишь плагинами к доменному. Я даже смогу просто взять и заменить UI‑слой на командную строку! Конечно, все эти идеи подкупают, в них хочется верить. Но есть одно «но». В реальной разработке мы зажаты в тиски: дизайнер принёс макеты, а бэкенд‑разработчик — API. Часто единственное, что нужно сделать, — написать адаптер от одного к другому. Такие приложения‑адаптеры обычно зовутся тонкими клиентами, бизнес‑логики в них мало. Получается, что мы — всего лишь прослойка (как бы грустно это ни звучало). Так android‑разработчики зарабатывают комплекс доменной неполноценности: с одной стороны, чистая архитектура учит нас чтить доменный слой, с другой стороны, кода у нас в нём — с гулькин нос. Тогда мы или начинаем молча страдать из‑за этого, или на цыпочках идём запихивать в доменные модули всё подряд, лишь бы объём кода вырос. Оба эти варианта ни к чему хорошему не приведут, я рекомендую остерегаться их. Моя рекомендация — немного расслабиться и сбавить градус ортодоксальности. Как это сделать? Надеюсь, следующая секция с этим поможет. Осторожно! Я уже предупреждал, но предупрежу ещё раз. Вас ждёт много вкусовщины и личного мнения (хоть оно и основано на горьком опыте). Читайте на свой страх и риск. Что делать с юзкейсом, содержимое которого — одна строчка? Вызов репозитория, и всё. Может, в этом случае вызывать репозиторий напрямую? Любая архитектура привносит избыточность. Эта избыточность нужна для единообразия, а единообразие нужно для того, чтобы код был очевидным. Такой код легко читать и легко поддерживать: он не преподносит сюрпризов. Если уж вы ввязались в «Чистую архитектуру» (вас же никто не заставлял?), то юзкейсы придётся писать всегда, даже однострочные. Ну а тесты уже на вашей совести 😉 У меня огромная вью‑модель (презентер, контроллер, etc.) с кучей логики. Она готовит данные для отображения. Может, эту логику унести в доменный слой? Там всё равно пусто. Хорошая попытка, но нет. В доменном слое не должно быть никаких намёков на то, как и кем будут отображаться данные. А вью‑модель можно просто разбить на части. Ладно, а навигация? Ведь удобно же, когда юзкейс сам общается с роутером/навигатором. Нет, нет, и ещё раз нет! Какие у вас экраны и как они сменяются — дело презентационное, и точка. Если юзкейсу суждено быть однострочным, смиритесь с этим, не надо пытаться его искусственно раздуть. Если presentation‑ и data‑слои — мелочи и детали реализации, то какой процент останется от приложения, если их удалить, а оставить только доменный слой? Очень небольшой. И хотя можно довольно точно описать все фичи приложения, прочитав только код доменного слоя, всё же нельзя считать слои данных и представления второстепенными. Их тоже надо холить и лелеять (и покрывать тестами, пусть там это делать и сложнее). А что, если рассматривать Android‑приложение лишь как часть большой системы? Ведь тогда всё встаёт на свои места: доменный слой располагается где‑то на бэкенде, а наше приложение и есть презентационный слой системы. Можно и так. Взять какую‑нибудь архитектуру из семейства MVx. То, что в «Чистой архитектуре» занимает целых два слоя, domain и data, в MVx — всего лишь буква M. Если эта самая модель совсем маленькая, не надо размазывать её по всяким UseCase, Entity и Repository, не тратьте своё время. Кодовая база — она как торт. Ну, согласитесь. Сложность приложения — это высота торта, и в этом измерении количество слоёв очень важно. Если торт высокий, ему нужно много слоёв, а если совсем низенький, то будет достаточно и трёх слоёв. Комплекс доменной неполноценности — это когда ваши слои толщиной с бумагу. Но вы прекрасно знаете, что с этим делать в следующий раз: не переусложнять. В этой ситуации главное не путать высоту торта с его объёмом. Торт может быть большим по площади (много фич), но невысоким. Со всех сторон нам говорят, что большим проектам нужна сложная архитектура. Но ведь площадь торта и его высота — это же совсем разные измерения (да‑да, площадь не измерение, но так нагляднее, чем говорить о длине и ширине). Ориентироваться при выборе архитектуры нужно не на количество фич, а на сложность самой сложной из них (тут придётся подумать наперёд, никуда не денешься). И тогда у вас всё получится, и никаких комплексов не будет.