TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.75K subscribers
Post #1912 1.89K
День 1567. #ЗаметкиНаПолях
Проверяем Правильность Архитектуры ПО с Помощью Тестов
Архитектура ПО — это план того, как структурировать систему. Вы можете строго или не очень строго следовать ему. Но когда сроки поджимают, и вы начинаете срезать углы, созданная вами прекрасная программная архитектура рассыпается, как карточный домик.

Архитектурные тесты — это автоматизированные тесты, которые проверяют структуру и дизайн кода. Вы можете использовать их для проверки соблюдения архитектуры ПО или направления зависимостей ваших проектов.

Архитектурные тесты пишутся так же, как и любой модульный тест. Есть отличная библиотека для создания архитектурных тестов, в которой уже реализован шаблонный код - NetArchTest.Rules.

Отправной точкой для написания архитектурных тестов является статический класс Types, который можно использовать для загрузки набора типов. После этого их можно дополнительно отфильтровать. Некоторые из доступных методов фильтрации:
- ResideInNamespace
- AreClasses
- AreInterfaces
- HaveNameStartingWith
- HaveNameEndingWith

Наконец, вы можете написать правило, которое хотите применить, вызвав Should или ShouldNot и применив условие, которое хотите проверить. Вот пример проверки того, что все классы домена запечатаны:
var result = Types
.InAssembly(DomainAssembly)
.That()
.AreClasses()
.Should()
.BeSealed()
.GetResult();
Assert.True(result.IsSuccessful);

Архитектурные тесты особенно полезны для проверки соблюдения правил архитектуры ПО в многоуровневой архитектуре или модульном монолите.
- Домен не должен иметь никаких зависимостей:
var result = Types
.InAssembly(DomainAssembly)
.ShouldNot()
.HaveDependencyOnAny("Application", "Infrastructure")
.GetResult();
Assert.True(result.IsSuccessful);

- Приложение не должно зависеть от Инфраструктуры:
var result = Types
.InAssembly(AplicationAssembly)
.Should()
.NotHaveDependencyOn("Infrastructure")
.GetResult();
Assert.True(result.IsSuccessful);

- Инфраструктура должна зависеть от Приложения и Домена
Здесь правило немного сложнее, т.к. мы пишем не отрицательный, а положительный фильтр. Поэтому ограничим выборку более конкретным набором типов. Например, что все репозитории должны иметь зависимость от пространства имен Домена.
var result = Types
.InAssembly(InfrastructureAssembly)
.HaveNameEndingWith("Repository")
.Should()
.HaveDependencyOn("Domain")
.GetResult();
Assert.True(result.IsSuccessful);

Ещё один ценный вариант использования — проверка соблюдения правил проектирования. Правила проектирования более конкретны и сосредоточены на деталях реализации классов. Например:
- Сервисы должны быть internal-классами,
- Сущности и объекты-значения должны быть запечатаны,
- Контроллеры не могут напрямую зависеть от репозиториев:
var result = Types
.InAssembly(ApiAssembly)
.That()
.HaveNameEndingWith("Controller")
.ShouldNot()
.HaveDependencyOn("Infrastructure.Repositories")
.GetResult();
Assert.True(result.IsSuccessful);

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

Источник: https://www.milanjovanovic.tech/blog/enforcing-software-architecture-with-architecture-tests
  • 👍 24
More from @netdeveloperdiary
  1. Sep 27, 2026День 2797. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Окончание Начало Продол…
  2. Sep 26, 2026День 2796. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Продолжение Начало Три…
  3. Sep 25, 2026День 2795. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Начало Проблема с позиц…
  4. Sep 24, 2026День 2794. #Оффтоп #Здоровье Сегодня будет необычный пост. Завтра в Москве стартует конфер…
  5. Sep 23, 2026День 2793. #ЗаметкиНаПолях #SQL 10 Редких Возможностей SQL, Которые Стоит Знать Каждому. Ч…
  6. Sep 22, 2026День 2792. #ЗаметкиНаПолях #SQL 10 Редких Возможностей SQL, Которые Стоит Знать Каждому. Ч…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →