Как проверить приложение на соответствие архитектуре слоев
Любому разработчику известен архитектурный шаблон слоев. При всей его незамысловатости он позволяет эффективно прятать реализацию и абстрагировать компоненты разного уровня. Слои нижнего уровня могут изменяться без особого риска испортить работу приложения, облегчен рефакторинг. Единственное очевидное условие, которое вы должны соблюдать – это придерживаться принятой архитектуры. Но иногда бывает, что программист нет-нет да и соблазняется вызвать пару методов «через голову». Например из слоя интерфейса обратиться прямиком в слой базы данных. Не будем здесь искать злого умысла, может этот случай был связан со спешкой при выпуске срочного исправления для заказчика. Но постепенно количество таких небольших «грешков» может свести на нет принятую когда то стройную архитектуру и вы опять окажетесь со «спагетти кодом». Вылавливать такие случаи несоответствия кода архитектуре слоев на большой системе может быть очень затруднительно. К счастью в Visual Studio 2010 (редакций Premium и Ultimate) есть инструменты, которые могут значительно облегчить эту задачу.
В Visual Studio 2010 есть компонент, который называется Layered Diagrams – диаграммы слоев. На первый взгляд это банальный инструмент рисования «кубиков». Замечательное же в нем то, что впоследствии вы можете сопоставить сборки вашего проекта конкретным слоям, и в автоматическом режиме проверить, нет ли среди кода приложения вызовов которые противоречат принятой архитектуре.
Давайте рассмотрим простой пример. Допустим, у нас есть классическое трехзвенное приложение с интерфейсом, слоем бизнес-логики и слоем базы данных.
Внутри команды всем очевиден порядок вызовов, и что не следует из интерфейса обращаться напрямую к слою БД. Когда у вас три сборки в проекте это возможно не будет проблемой. Но когда их у вас станет штук десять, держать в голове кто кого и из какого слоя может вызвать, станет затруднительно. Поэтому задокументируем нашу схему добавив в Solution проект с типом Modelling (File/Add New Project/Modelling Projects/Modelling Project):
Далее добавляем диаграмму слоев (Add New Item/Layer Diagram) и рисуем нашу архитектуру слоев:
Давайте сознательно допустим логическую ошибку в архитектуре слоев прямо в коде. Добавим референс на DbLayer и вызовем его прямо из UILayer:
Если у вас сложная система, обнаружить такой вызов при сотнях коммитов в неделю может быть очень трудно. Но постепенно ваше решение будет превращаться в кашу. Что же делать?
Создаем сопоставление слоев сборкам.
На самом деле нам осталось проделать еще один шаг после того как созданы основные компоненты системы в виде сборок и нарисована диаграмма слоев. Необходимо сопоставить их между собой, просто перетащив из Solution Explorer узлы проектов на прямоугольники слоев:
При этом в правом верхнем углу будет отображаться количество сборок сопоставленных с этим слоем, а в Modelling проекте появятся ссылки на компоненты решения:
Теперь все готово для автоматической проверки архитектуры, достаточно вызвать контекстное меню на диаграмме слоев:
После непродолжительного анализа, который работает через Reflection мы получим список несоответствий нашего кода архитектуре:
И там будет тот самый вызов, который мы сознательно внесли в код, идущий в разрез с текущей архитектурой решения:
Error 1 AV0001: Invalid Dependency: UILayer.MainWindow.CalculateDiscount_Click(Method) --> DbLayer.Customer.IsHabraUser(Field)
После того как вы сделаете рефакторинг (в нашем простом случае просто перенесем вызов из UI в Business Logic), валидация архитектуры будет приводить к таким результатам:
Что говорит нам о том, что код нашего решения полностью соответствует принятой архитектуре слоев. Если понадобится, вы можете настроить проверку соответствия кода архитектуре слоев в автоматическом режиме, например при сборке проекта в TFS с помощью MSBuild (на Русском языке).