Clean Architecture.

Чистая архитектура по новому. Part 2.

Nikita Goncharuk
Clean Code

--

За последние несколько лет мы увидели целый ряд идей относительно архитектуры систем. Они включают:

Хотя все эти архитектуры несколько различаются по своим деталям, они очень похожи. У них всех одна цель — разделение интересов. Все они достигают этого разделения, разделяя программное обеспечение на слои. У каждого есть по крайней мере один уровень для бизнес-правил, а другой — для интерфейсов.

Каждая из этих архитектур производит системы, которые:

  1. Независимы от рамок. Архитектура не зависит от наличия некоторой библиотеки программного обеспечения с широкими возможностями. Это позволяет вам использовать фреймворки в качестве инструментов, а не встраивать вашу систему в их ограничения.
  2. Тестируемые. Бизнес-правила могут быть протестированы без пользовательского интерфейса, базы данных, веб-сервера или любого другого внешнего элемента.
  3. Независимы от пользовательского интерфейса. Пользовательский интерфейс может быть легко изменен без изменения остальной части системы. Веб-интерфейс можно заменить консольным, например, без изменения бизнес-правил.
  4. НезависимыThe Dependency Rule от базы данных. Вы можете заменить Oracle или SQL Server на Mongo, BigTable, CouchDB или что-то еще. Ваши бизнес-правила не привязаны к базе данных.
  5. Независимо от какого-либо внешнего агентства. На самом деле ваши бизнес-правила просто ничего не знают о внешнем мире.

Диаграмма в верхней части этой статьи является попыткой объединить все эти архитектуры в единую действенную идею.

The Dependency Rule

Правило зависимости. Концентрические круги представляют различные области программного обеспечения. В общем, чем дальше, тем выше уровень программного обеспечения. Внешние круги — это механизмы. Внутренние круги — это политика.

Основным правилом, которое заставляет эту архитектуру работать, является правило зависимости. Это правило говорит, что зависимости исходного кода могут указывать только внутрь. Ничто во внутреннем круге не может знать о чем-то во внешнем круге. В частности, имя чего-либо, объявленного во внешнем круге, не должно упоминаться кодом во внутреннем круге. Это включает в себя, функции, классы. переменные или любой другой названный программный объект.

Точно так же форматы данных, используемые во внешнем круге, не должны использоваться внутренним кругом, особенно если эти форматы создаются структурой во внешнем круге. Мы не хотим, чтобы что-то во внешнем круге влияло на внутренние круги.

Entities

Объекты. Объекты инкапсулируют корпоративные бизнес-правила. Сущность может быть объектом с методами или набором структур данных и функций. Это не имеет значения, поскольку объекты могут использоваться многими различными приложениями на предприятии.

Если у вас нет предприятия и вы пишете только одно приложение, то эти объекты являются бизнес-объектами приложения. Они заключают в себе самые общие и высокоуровневые правила. Они наименее вероятно изменятся, когда что-то внешнее меняется. Например, вы не ожидаете, что эти объекты будут затронуты изменением навигации по страницам или безопасности. Никакие оперативные изменения в каком-либо конкретном приложении не должны влиять на уровень объекта.

Use Cases

Случаи применения. Программное обеспечение на этом уровне содержит специфические бизнес-правила для приложений. Он инкапсулирует и реализует все варианты использования системы. Эти сценарии использования управляют потоком данных между объектами и от них и дают указание этим субъектам использовать бизнес-правила в масштабах предприятия для достижения целей варианта использования.

Мы не ожидаем, что изменения в этом слое затронут объекты. Мы также не ожидаем, что на этот уровень будут влиять изменения внешних факторов, таких как база данных, пользовательский интерфейс или какие-либо из общих структур. Этот слой изолирован от таких проблем.

Нo, однако, ожидайте, что изменения в работе приложения повлияют на варианты использования и, следовательно, на программное обеспечение на этом уровне. Если подробности варианта использования изменятся, то некоторый код в этом слое, несомненно, будет затронут.

Interface Adapters

Интерфейсные адаптеры. Программное обеспечение в этом слое представляет собой набор адаптеров, которые преобразуют данные из формата, наиболее удобного для вариантов использования и сущностей, в формат, наиболее удобный для некоторого внешнего агентства, такого как База данных или Интернет. Например, именно этот уровень будет полностью содержать архитектуру MVC GUI. Презентаторы, Представления и Контроллеры все принадлежат здесь. Модели, скорее всего, представляют собой просто структуры данных, которые передаются из контроллеров в сценарии использования, а затем обратно из сценариев использования в докладчики и представления.

Точно так же на этом уровне данные преобразуются из формы, наиболее удобной для сущностей и вариантов использования, в форму, наиболее удобную для любой используемой инфраструктуры постоянства. т.е. база данных. Никакой код внутри этого круга вообще ничего не должен знать о базе данных. Если база данных является базой данных SQL, тогда весь SQL должен быть ограничен этим уровнем, и в частности частями этого уровня, которые имеют отношение к базе данных.

Также на этом уровне есть любой другой адаптер, необходимый для преобразования данных из некоторой внешней формы, такой как внешняя служба, во внутреннюю форму, используемую сценариями использования и сущностями.

Frameworks and Drivers.

Каркасы и Драйверы. Внешний слой обычно состоит из фреймворков и инструментов, таких как база данных, веб-фреймворк и т. д. Как правило, вы не пишете много кода на этом слое, кроме склеивания кода, который связывается со следующим кругом внутри.

Этот слой, где все детали проходят. Интернет это деталь. База данных является деталью. Мы держим эти вещи снаружи, где они могут навредить.

Only Four Circles?

Только четыре круга? Нет, круги схематичны. Вы можете обнаружить, что вам нужно больше, чем только эти четыре. Нет правила, которое гласит, что вы должны всегда иметь только эти четыре. Тем не менее, правило зависимости всегда применяется. Зависимости исходного кода всегда указывают внутрь. По мере продвижения внутрь уровень абстракции увеличивается. Внешний круг — низкоуровневая бетонная деталь. По мере продвижения внутрь программное обеспечение становится все более абстрактным и инкапсулирует политики более высокого уровня. Самый внутренний круг — самый общий.

Crossing boundaries.

Пересечение границ. В правом нижнем углу диаграммы показан пример того, как мы пересекаем границы круга. На нем показаны контроллеры и презентаторы, взаимодействующие с вариантами использования на следующем уровне. Обратите внимание на поток контроля. Он начинается в контроллере, проходит через сценарий использования, а затем завершается выполнением в презентаторе. Обратите внимание также на зависимости исходного кода. Каждый из них направлен внутрь на случаи использования.

Мы обычно разрешаем это очевидное противоречие, используя принцип инверсии зависимости. Например, в таком языке, как Java, мы бы организовали интерфейсы и отношения наследования таким образом, чтобы зависимости исходного кода противодействовали потоку управления только в нужных точках через границу.

Например, учтите, что в случае использования необходимо позвонить докладчику. Однако этот вызов не должен быть прямым, потому что это нарушило бы правило зависимости: внутренний круг не может упомянуть имя во внешнем круге. Таким образом, у нас есть вариант использования, вызывающий интерфейс (показанный здесь как порт вывода варианта использования) во внутреннем круге, и презентатор во внешнем круге реализует его.

Та же самая техника используется, чтобы пересечь все границы в архитектурах. Мы используем преимущества динамического полиморфизма для создания зависимостей исходного кода, которые противостоят потоку управления, чтобы мы могли соответствовать правилу зависимости независимо от того, в каком направлении движется поток управления.

What data crosses the boundaries.

Какие данные пересекают границы. Обычно данные, которые пересекают границы, представляют собой простые структуры данных. Вы можете использовать базовые структуры или простые объекты Data Transfer, если хотите. Или данные могут быть просто аргументами в вызовах функций. Или вы можете упаковать его в hashmap или создать в виде объекта. Важно то, что изолированные, простые структуры данных передаются через границы. Мы не хотим обманывать и передавать строки сущностей или баз данных. Мы не хотим, чтобы структуры данных имели какую-либо зависимость, которая нарушает правило зависимости.

Например, многие платформы баз данных возвращают удобный формат данных в ответ на запрос. Мы могли бы назвать это RowStructure. Мы не хотим передавать эту структуру строк внутрь границы. Это нарушило бы правило зависимости, потому что заставило бы внутренний круг что-то узнать о внешнем круге.

Поэтому, когда мы передаем данные через границу, они всегда находятся в форме, наиболее удобной для внутреннего круга.

Conclusion

Заключение. Соблюдать эти простые правила не сложно, и вы избавитесь от многих головных болей в будущем. Разделив программное обеспечение на слои и соблюдая Правило зависимости, вы создадите систему, которая может быть проверена по своей сути, со всеми вытекающими отсюда преимуществами. Когда какая-либо из внешних частей системы устареет, например, база данных или веб-инфраструктура, вы можете заменить эти устаревшие элементы с минимальными усилиями.

Translation: blog.cleancoder.com
Help us with your claps:)

--

--