Вольный перевод статьи Robert C. Martin "Clean Architecture"
Чистая архитектура
Всего за несколько недель после того, как я начал говорить о необходимости чистки нашей архитектуры, заметил удивительное сопротивление этой идее. Очевидно, что мнение о том, что хорошо было бы скрывать фреймворк, UI или БД от кода нашего приложения, не является общепринятым.
Есть одно несколько отличное мнение, высказанное Разочарованным Архитектором (The Frustrated Architect) в его блоге, где он показывает картинку, которую я повторю:
Он пытается донести мысль, что, если UI и БД являются гораздо большей частью системы, чем бизнес-логика, то архитектура системы должна быть в большей мере ориентирована на эти более крупные элементы. Я, конечно, не согласен. Независимо от того, насколько велика какая-либо часть системы, остальные части должны быть отделены от нее.
Другие несогласные (или, возможно, более подходящее слово - “скептически настроенные”) взгляды были менее формальными. Один человек задал мне вопрос: “А вы вообще делали это в Rails проекте?”, как будто Rails был чем-то особенным и настолько изменил игру, что нормальные правила хорошего проектирования больше не применяются.
Другие ребята беспокоятся, что результатом моего совета будет куча дублирующегося кода и многократное копирование данных из одной структуры данных в другую через все уровни системы. И этого я, конечно же, не хочу; ничто из того, что я советовал, не приведёт к повторению структур данных и нарушению копирования полей. Позже я объясню почему.
Была одна особенно яркая жалоба: “Эти слова слишком громкие, я хочу увидеть код”. Хотя я сочувствую этой точке зрения, представленные здесь концепции не так сложны для понимания; и, на самом деле, большое количество кода может сокрыть их больше, чем помочь.
Никакой это не Rocket Science
Никакой это не Rocket Science. Главная идея очень проста. Вы разделяете UI от бизнес-логики, передавая простые структуры данных между ними, не позволяете своим контроллерам ничего знать о бизнес-логике. Вместо этого контроллеры распаковывают HttpRequest в простую ванильную структуру данных, а затем передают эту структуру данных объекту-интерактору, который реализует сценарий использования, вызывая бизнес-объекты. Затем интерактор собирает данные ответа в другую ванильную структуру данных и передает их обратно в UI. Представления ничего не знают о бизнес-объектах, а просто смотрят в эту структуру данных и представляют ответ. На деле, конечно, деталей больше, и они хорошо описаны в ссылках выше. Но, на самом деле, это все, что нужно сделать.
Выгода должна быть очевидной. Код приложения полностью отделен от UI. Вы можете тестировать код без UI представления. Не нужно запускать веб-сервер, или контейнер, или Rails, или любой другой фреймворк для запуска ваших тестов. Более того, если текущий UI вам не нравится - можно заменить его другим.
Идеальная ли это схема? Конечно, нет. Возможно ли, что один тип UI быть настолько отличным от другого, что они не смогу использовать общий интерфейс? Возможно. Значит ли это то, что подобная техника - пустая трата времени? Да ты шутишь, что ли?
Это будет меня тормозить
Нет, не будет. Ради всего святого, вас это еще и ускорит. Вы сможете запускать свои тесты без задержки, откладывать принятия решений относительно вашего UI, тестировать бизнес-логику без UI представления. Такая гибкость и разделение всегда будут ускорять вашу работу. Хоть одну вещь за последние пятьдесят лет мы усвоили. Нет ничего лучше, чем то, что тебя тормозит.
Мы не должны откладывать решения
Одним из моих самых резких высказываний было то, что хорошая архитектура позволяет вам откладывать критичные решения по поводу UI, фреймворков, баз данных и прочего. Некоторые люди говорят, что клиенты не хотят отложенного UI, а администраторы - отложенных баз данных. От итерации к итерации, они хотят видеть полностью рабочую систему, включая UI, БД и фреймворки, и не хотят, чтобы итерация проводилась исключительно по бизнес-правилам. Действительно, хорошая agile практика требует длинных тонких срезов по всей архитектуре.
Со всем этим я согласен, конечно. Однако длинные тонкие срезы не должны быть связаны между собой. Хорошая архитектура не заставляет, а позволяет вам откладывать критичные решения. И, если вы можете их отложить, то получите большую гибкость. Например, для нескольких первых спринтов сможете создать простой промежуточный UI, и только потом заменить его на более функциональный.
Что насчёт GOOS?
Одной из лучших книг по проектированию ПО является “Growing Object Oriented Software” от Стива Фримана и Ната Прайса. Они рекомендуют сторонний подход к разработке систем. Вы начинаете с интерфейса и переходите к бизнес-правилам.
На первый взгляд, звучит это всё так, будто я противоречу своему совету. В конце концов, я фокусируюсь на юзкейсах и считаю UI маленькой раздражающей деталью. Тем не менее, нет ничего плохого в том, чтобы сначала работать с раздражающими небольшими деталями, если вы отделите от них свои бизнес-правила. В идеологии GOOS нет ничего, что препятствовало бы отделению бизнес-правил от UI.
По правде говоря, я не следую методологии GOOS, а предпочитаю другой подход: сначала фокусироваться на бизнес-правилах, и только после этого добавлять UI вокруг. Но это не значит, что GOOS плох (это не так) или что, используя эту технику, вы не добьетесь разделенной архитектуры (а вы добейтесь!).
Oh no, it’s Big Up Front Design!
Нет, все не так. Я не говорю вам месяцами рисовать UML диаграммы. Я говорю вам разделять. Можно разделять, пока вы пишете код и выполняете тесты. Не нужен предварительный план, чтобы создать красиво разделенную архитектуру. Все, что нужно сделать - это думать о проблеме, для решения которой вы пишете код.
Однако, я должен отметить, что нет ничего плохого в том, чтобы потратить несколько часов или даже дней, чтобы обдумать форму вашей системы. Нет ничего плохого в том, чтобы нарисовать несколько UML или прочих диаграмм, чтобы получить парочку идей о структуре вашей системы. Я не прошу вас делать это месяцами, но нет ничего плохого в обдумывании. (см.: Hammock Driven Development)
Это не ново
Я был удивлен реакциям на эти идеи. Понимаю, что люди сопротивляются переменам, и множество программистов еще не привыкли к идеям разделения (прочтите это предложение несколько раз и похнычьте). Но это не новые идеи, которые снизошли до меня, а старые. Они пришли от людей, вроде Дэвида Парнаса, Тома Демарко, Грейди Бутча, Ивара Якобсона и многих других. Факт того, что идеи стары, не означает, что они хороши, но в этом случае - означает.
Что с нами стало? Как мы могли забыть об этих правилах? Когда они успели испариться из нашего сознания? Неужели мы настолько наивны и, собрав в кучу компоненты, надеемся построить сложную систему, потрясывая ее пока все не заработает?
Top comments (0)