[Java] Улучшение модификаторов видимости Java с помощью ArchUnit (перевод)
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Инкапсуляция и отделение внутренних компонентов от public, вероятно, является одним из наиболее недооцененных методов программирования, когда речь идет о обеспечении длительной поддержки приложения.К счастью, в Java есть нечасто используемый модификатор видимости package-private, который очень помогает скрыть нежелательные детали реализации. К сожалению, если количество внутренних классов велико, оно плохо масштабируется, но, к счастью, нам может помочь ArchUnit.Public vs PrivateРазделение private и public позволяет уменьшить связность и получить свободу изменения деталей реализации, не беспокоясь о внесении нежелательных критических изменений.
Примером из реальной жизни может служить одна из библиотек автора - параллельные сборщики. Благодаря минимизации размера общедоступного API у меня была возможность несколько раз реорганизовать внутреннюю архитектуру, не рискуя внести какие-либо критические изменения на уровне API.Если бы я этого не сделал, мои руки были бы связаны, так как кто-то мог бы использовать некоторые из моих внутренних классов напрямую.То же самое относится к любому другому модулю или классу, который должен взаимодействовать с чем-то еще.Возможности package-privateДля скрытия внутренней структуры пакета можно использовать модификатор package-private и ограничить видимость классов, к которым не следует иметь доступ извне пакета.Давайте посмотрим на типичную структуру пакета:
В этом варианте, к сожалению, нам нужно оставить все внутренние классы public, потому что видимость package-private работает в пределах одного пакета, а не всей иерархии.Учитывая это, если мы хотим использовать package-private, нам нужно будет разместить их все в одном пакете:
К сожалению, такой подход плохо масштабируется с увеличением количества классов.Представляем ArchUnitК счастью, у нас может иметься как внутренняя структура пакета, так и ограничения видимости благодаря библиотеке ArchUnit, которую можно использовать для обеспечения соблюдения архитектурных соглашений.Например, мы можем воссоздать функциональность иерархического модификатора package-private, ограничив доступ к классам в подпакетах com.pivovarit.movies классами, находящимися во всей иерархии пакетов:
public class ArchitectureTest {
private static final JavaClasses classes = new ClassFileImporter()
// ...
.importPackages("com.pivovarit");
@Test
void com_pivovarit_movies_shouldNotExposeInternalClasses() {
classes().that().resideInAPackage("com.pivovarit.movies.*")
.should()
.onlyBeAccessed().byClassesThat()
.resideInAPackage("com.pivovarit.movies..")
.check(classes);
}
}
А теперь, если мы создадим класс вне пакета и будем использовать public API (Rentals), тесты будут зелеными:
package com.pivovarit;
import com.pivovarit.movies.Rentals;
public class Starter {
public static void main(String[] args) {
Rentals instance = Rentals.instance();
boolean rent = instance.rent(42);
}
}
Но если мы попытаемся получить доступ к MovieDetailsRepository напрямую, мы получим нарушение:
package com.pivovarit;
import com.pivovarit.movies.repository.MovieDetailsRepository;
public class Starter {
public static void main(String[] args) {
MovieDetailsRepository movieDetailsRepository
= new MovieDetailsRepository();
// java.lang.AssertionError: Architecture Violation
}
}
Расширяя идеюЕстественно, ArchUnit можно использовать для обеспечения соблюдения множества соглашений, например, в проекте, упомянутом ранее, он используется для обеспечения соблюдения политики нулевых зависимостей:
@Test
void shouldHaveZeroDependencies() {
classes().that().resideInAPackage("com.pivovarit.collectors")
.should()
.onlyDependOnClassesThat()
.resideInAnyPackage("com.pivovarit.collectors", "java..")
// ...
.check(classes);
}
… Или обеспечить существование единственного public класса:
@Test
void shouldHaveSingleFacade() {
classes().that().arePublic()
.should().haveSimpleName("ParallelCollectors")
.andShould().haveOnlyPrivateConstructors()
.andShould().haveModifier(FINAL)
// ...
.check(classes);
}
Больше примеров использования ArchUnit можно найти на официальной странице.ЗаключениеОтделение внутренних компонентов от public - один из лучших способов повысить удобство сопровождения вашего программного обеспечения. К сожалению, собственные инструменты Java ограничены, но ArchUnit может охватить те случаи, когда Java не может.Конечно, приведенные выше примеры - это просто основа, на которой вы можете опираться. Реальная жизнь полна более сложных случаев.Тем не менее, ArchUnit может помочь вам улучшить ваш public API. Но ArchUnit не поможет, если вы продолжите добавлять все больше и больше исключений в свои правила.Примеры из этой статьи можно найти на GitHub.
Примечание переводчика. Дополнительно о применении ArchUnit можно прочитать:Модульное тестирование архитектуры Spring Boot проекта с помощью ArchUnitОбнаружение и удаление кода без ссылок с помощью ArchUnitВнедрение рекомендаций по структуре кода с использованием ArchUnitОбеспечение границ компонентов чистой архитектуры с помощью Spring Boot и ArchUnit
===========
Источник:
habr.com
===========
===========
Автор оригинала: Grzegorz Piwowarek
===========Похожие новости:
- [ECM/СЭД] Content Services Platform — новая реинкарнация систем электронного документооборота
- [API, Dart] Dart на сервере
- [Python, Алгоритмы, API, 1С] Tesseract vs таблицы. Распознавание документов. Часть 2
- [Программирование, Промышленное программирование, Управление разработкой, Распределённые системы] Предварительная оптимизация — корень всех зол?
- Google одержал победу в разбирательстве с Oracle, связанном с Java и Android
- [Информационная безопасность, Разработка под iOS, Разработка мобильных приложений, API, Монетизация мобильных приложений] Apple запрещает использовать рекламные SDK для создания цифрового отпечатка пользователя
- [Java, Микросервисы] Собственный провайдер пользователей для Keycloak
- [JavaScript, Научно-популярное, Космонавтика] Для чего космическому кораблю крылья?
- [Разработка веб-сайтов, JavaScript, Программирование, TypeScript] Совет #1 по ознакомлению с новыми кодовыми базами JavaScript (перевод)
- [Java, .NET] «Microsoft Coffee»: первоапрельский ответ на Java
Теги для поиска: #_java, #_api, #_arhitektura (архитектура), #_java
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 19:42
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Инкапсуляция и отделение внутренних компонентов от public, вероятно, является одним из наиболее недооцененных методов программирования, когда речь идет о обеспечении длительной поддержки приложения.К счастью, в Java есть нечасто используемый модификатор видимости package-private, который очень помогает скрыть нежелательные детали реализации. К сожалению, если количество внутренних классов велико, оно плохо масштабируется, но, к счастью, нам может помочь ArchUnit.Public vs PrivateРазделение private и public позволяет уменьшить связность и получить свободу изменения деталей реализации, не беспокоясь о внесении нежелательных критических изменений. Примером из реальной жизни может служить одна из библиотек автора - параллельные сборщики. Благодаря минимизации размера общедоступного API у меня была возможность несколько раз реорганизовать внутреннюю архитектуру, не рискуя внести какие-либо критические изменения на уровне API.Если бы я этого не сделал, мои руки были бы связаны, так как кто-то мог бы использовать некоторые из моих внутренних классов напрямую.То же самое относится к любому другому модулю или классу, который должен взаимодействовать с чем-то еще.Возможности package-privateДля скрытия внутренней структуры пакета можно использовать модификатор package-private и ограничить видимость классов, к которым не следует иметь доступ извне пакета.Давайте посмотрим на типичную структуру пакета: В этом варианте, к сожалению, нам нужно оставить все внутренние классы public, потому что видимость package-private работает в пределах одного пакета, а не всей иерархии.Учитывая это, если мы хотим использовать package-private, нам нужно будет разместить их все в одном пакете: К сожалению, такой подход плохо масштабируется с увеличением количества классов.Представляем ArchUnitК счастью, у нас может иметься как внутренняя структура пакета, так и ограничения видимости благодаря библиотеке ArchUnit, которую можно использовать для обеспечения соблюдения архитектурных соглашений.Например, мы можем воссоздать функциональность иерархического модификатора package-private, ограничив доступ к классам в подпакетах com.pivovarit.movies классами, находящимися во всей иерархии пакетов: public class ArchitectureTest {
private static final JavaClasses classes = new ClassFileImporter() // ... .importPackages("com.pivovarit"); @Test void com_pivovarit_movies_shouldNotExposeInternalClasses() { classes().that().resideInAPackage("com.pivovarit.movies.*") .should() .onlyBeAccessed().byClassesThat() .resideInAPackage("com.pivovarit.movies..") .check(classes); } } package com.pivovarit;
import com.pivovarit.movies.Rentals; public class Starter { public static void main(String[] args) { Rentals instance = Rentals.instance(); boolean rent = instance.rent(42); } } package com.pivovarit;
import com.pivovarit.movies.repository.MovieDetailsRepository; public class Starter { public static void main(String[] args) { MovieDetailsRepository movieDetailsRepository = new MovieDetailsRepository(); // java.lang.AssertionError: Architecture Violation } } @Test
void shouldHaveZeroDependencies() { classes().that().resideInAPackage("com.pivovarit.collectors") .should() .onlyDependOnClassesThat() .resideInAnyPackage("com.pivovarit.collectors", "java..") // ... .check(classes); } @Test
void shouldHaveSingleFacade() { classes().that().arePublic() .should().haveSimpleName("ParallelCollectors") .andShould().haveOnlyPrivateConstructors() .andShould().haveModifier(FINAL) // ... .check(classes); } Примечание переводчика. Дополнительно о применении ArchUnit можно прочитать:Модульное тестирование архитектуры Spring Boot проекта с помощью ArchUnitОбнаружение и удаление кода без ссылок с помощью ArchUnitВнедрение рекомендаций по структуре кода с использованием ArchUnitОбеспечение границ компонентов чистой архитектуры с помощью Spring Boot и ArchUnit
=========== Источник: habr.com =========== =========== Автор оригинала: Grzegorz Piwowarek ===========Похожие новости:
|
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 19:42
Часовой пояс: UTC + 5