Если архитектура программного обеспечения выполнена в соответствии с разумным стандартом, мы должны ожидать:
- Хорошо разработанные шаблоны, которые могут соответствовать как функциональным, так и нефункциональным требованиям.
- Никакой сумасшедшей сумасшедшей связи, проблемы правильно разделены, и все поддается проверке.
Если мы это получим, мы должны быть уверены, что по мере развития программного обеспечения оно будет обслуживаемым. Таким образом, сложная часть заключается в том, что слишком часто архитектурные правила отлично начинаются на доске или слайде PowerPoint, но просто теряются в коде, потому что их слишком сложно применять.
Arch Unit — это супер механизм для реализации некоторых архитектурных правил и шаблонов в вашей кодовой базе. Прошло около нескольких лет, но кое-что только я обнаружил в этом году. Я сталкивался с этим, когда пытался придумать, как пакет « утилит », пресловутый, не превратился в пресловутый « дампинг ». В идеале, у нас никогда не было бы пакетов утилит, но в реальном мире они почти всегда существуют. У пакета utils не должно быть много эфферентных зависимостей . Например, предположим, у вас есть пакет с названием ShoppingCart . Тогда вам понадобится какая-то полезная функция, чтобы добавить всего две корзины, удалить специальные предложения, добавить скидки лояльности, бла-бла-бла. Последнее, что вы хотите увидеть, это кто-то проверяет это в пакете utils с зависимостями от пакета shoppingcart. Потому что, если он так сфокусирован на покупательской корзине, он действительно должен быть в пакете покупательской тележки. Если это произойдет, очень скоро ваш пакет утилит будет зависеть от всего, и все будут зависеть от него. Катастрофа. Какой смысл в пакетах, если что-то может зависеть только от чего-либо. Они перестанут предоставлять какие-либо преимущества в отношении интервалов имен или инкапсуляции.
Итак, как Arch Arch может помочь? Очень просто, вы определяете архитектурные правила как тест JUnit. Подождите секунду … Это тест JUnit. Пакет efferent (внешний) и afferent (внутренний) для вас utils очень просто выражается как:
|
1
2
3
4
5
|
@ArchTestpublic static final ArchRule utilPackageDependenciesRules = classes().that().resideInAPackage("com.company.application.util") .should().onlyDependOnClassesThat().resideInAnyPackage(getAllowedDependencies("com.company.application.exception")) .andShould().onlyHaveDependentClassesThat().resideInAnyPackage("com.company.application.shoppingcart" "com.company.application.payment); |
Ну это все. Теперь повторите для каждого пакета, и у нас есть контроль кода. Работает как любой другой тест JUnit. Таким образом, поэтому он будет легко работать как часть вашего CI и т. Д. Теперь, если вы хорошо спроектировали свои пакеты, вам не нужно постоянно проверять код. Вместо этого правила являются частью вашего тестирования. По мере развития вашего программного обеспечения, появления новых пакетов и изменения правил зависимостей, просто измените правила, выраженные в хороших API-интерфейсах. Кто-то новый присоединяется к командам и хочет быстро освоить архитектурные правила — просто, просто посмотрите на архитектурные тесты.
ArchUnit не только дает вам возможность выражать правила пакета, вы также можете определять свои собственные правила или условия, а затем применять их к любому коду, который вы хотите. Например, предположим, что вы хотите условие, что объект является неизменным. Поэтому вы, естественно, не хотите сеттеров. Это может быть выражено этим условием.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
static ArchCondition noPublicSettersCondition = new ArchCondition("class has no public setters") { @Override public void check(JavaClass item, ConditionEvents events) { for (JavaMethod javaMethod: item.getMethods()) { if (javaMethod.getName().startsWith("set") && javaMethod.getModifiers().contains(JavaModifier.PUBLIC)) { String message = String.format( "Public method %s is not allowed begin with setter", javaMethod.getName()); events.add(SimpleConditionEvent.violated(item, message)); } } } }; |
Затем вы можете применить условие noSetter к любому пользовательскому исключению, которое может написать разработчик. Не было бы хорошо, если бы у Исключения был сеттер, не так ли?
|
1
2
3
|
@ArchTest public static final ArchRule noExceptionsHaveSetters = classes().that() .areAssignableTo(RuntimeException.class).should(noSettersCondition); |
Предположим, вы продолжаете замечать, что логгеры, определенные в классах либо
не являются частными, не являются статичными или не являются окончательными . Не тратьте время на разговоры об этом. ArchUnit это!
|
1
2
3
4
5
6
7
|
@ArchTest public final ArchRule loggers_should_be_private_static_final = fields().that().haveRawType(TaLogger.class) .should().bePrivate() .andShould().beStatic() .andShould().beFinal() .because("we agreed on this convention"); |
Таким образом, цель на самом деле здесь — концептуализировать хорошие правила, которые помогут вам оставаться тестируемыми и поддерживаемыми, применять их так, чтобы их было легко проверить и понять. ArchUnit действительно отличный инструмент для библиотеки.
|
Опубликовано на Java Code Geeks с разрешения Алекса Стейвли, партнера нашей программы JCG . Смотреть оригинальную статью здесь: Arch Unit Мнения, высказанные участниками Java Code Geeks, являются их собственными. |