From 010d71a90da8e7a3f2f8662af9d86f844c90d3a4 Mon Sep 17 00:00:00 2001 From: mnhock Date: Tue, 11 Jun 2024 15:27:27 +0200 Subject: [PATCH] Add user guide Closes gb-17 --- docs/USERGUIDE.md | 242 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 242 insertions(+) diff --git a/docs/USERGUIDE.md b/docs/USERGUIDE.md index e69de29..039a389 100644 --- a/docs/USERGUIDE.md +++ b/docs/USERGUIDE.md @@ -0,0 +1,242 @@ +## Taikai + +### 1. Introduction +Taikai is an automated architecture testing tool for Java projects designed to maintain clean and consistent architecture. It enforces predefined and custom architectural constraints, ensuring code quality, maintainability, and adherence to best practices. + +### 2. Getting Started +To use Taikai, include it as a dependency in your Maven pom.xml: + +```javaxml + + com.enofex + taikai + ${taikai.version} + test + +``` + +Architecture rules are defined using Taikai's fluent API, allowing developers to specify constraints on classes, methods, imports, naming conventions, and more. Taikai provides pre-defined configurations for common architectural patterns and best practices. + +### 3. Usage + +#### Test Configuration + +Test configuration involves specifying constraints related to testing frameworks and practices. Let's explore the rules defined in the provided source code: + +- **JUnit 5 Configuration**: Ensure that JUnit 5 test classes and methods are not annotated with `@Disabled`. + +```java +Taikai.builder() + .namespace("com.company.yourproject") + .test(test -> test + .junit5(junit5 -> junit5 + .classesShouldNotBeAnnotatedWithDisabled() + .methodsShouldNotBeAnnotatedWithDisabled())) + .build() + .check(); +``` + +#### Java Configuration + +Java configuration involves defining constraints related to Java language features, coding standards, and architectural patterns. Let's examine the rules defined in the provided source code: + +- **No Usage of Deprecated APIs**: Ensure that deprecated APIs are not used in the codebase. + +```java +Taikai.builder() + .namespace("com.company.yourproject") + .java(java -> java + .noUsageOfDeprecatedAPIs()) + .build() + .check(); +``` + +- **Classes Should Implement `hashCode` and `equals`**: Ensure that classes override the `hashCode` and `equals` methods for proper object comparison. + +```java +Taikai.builder() + .namespace("com.company.yourproject") + .java(java -> java + .classesShouldImplementHashCodeAndEquals()) + .build() + .check(); +``` + +- **Methods Should Not Throw Generic Exception**: Ensure that methods do not throw generic exceptions and use specific exception types instead. + +```java +Taikai.builder() + .namespace("com.company.yourproject") + .java(java -> java + .methodsShouldNotThrowGenericException()) + .build() + .check(); +``` + +- **Utility Classes Should Be Final and Have Private Constructor**: Ensure that utility classes are declared as `final` and have private constructors to prevent instantiation. + +```java +Taikai.builder() + .namespace("com.company.yourproject") + .java(java -> java + .utilityClassesShouldBeFinalAndHavePrivateConstructor()) + .build() + .check(); +``` + +- **Imports Configuration**: Ensure that there are no cyclic dependencies in imports and disallow specific imports. + +```java +Taikai.builder() + .namespace("com.company.yourproject") + .java(java -> java + .imports(imports -> imports + .shouldHaveNoCycles() + .shouldNotImport("..shaded..") + .shouldNotImport("..lombok.."))) + .build() + .check(); +``` + +- **Naming Configuration**: Define naming conventions for classes, constants, and interfaces. + +```java +Taikai.builder() + .namespace("com.company.yourproject") + .java(java -> java + .naming(naming -> naming + .classesShouldNotMatch(".*Impl") + .constantsShouldFollowConvention() + .interfacesShouldNotHavePrefixI()))) + .build() + .check(); +``` + +#### Spring Configuration + +Spring configuration involves defining constraints specific to Spring Framework usage. Let's incorporate the Spring-related rules defined in the provided source code: + +- **No Autowired Fields Configuration**: Ensure that fields are not annotated with `@Autowired` and constructor injection is preferred. + +```java +Taikai.builder() + .namespace("com.company.yourproject") + .spring(spring -> spring + .noAutowiredFields()) + .build() + .check(); +``` + +- **Spring Boot Configuration**: Ensure that the main application class annotated with `@SpringBootApplication` is in the default package. + +```java +Taikai.builder() + .namespace("com.company.yourproject") + .spring(spring -> spring + .boot(boot -> boot + .springBootApplicationShouldBeIn("com.company.yourproject"))) + .build() + .check(); +``` + +- **Configurations Configuration**: Ensure that configuration classes end with "Configuration" or match a specific regex pattern. + +```java +Taikai.builder() + .namespace("com.company.yourproject") + .spring(spring -> spring + .configurations(configuration -> configuration + .namesShouldEndWithConfiguration() + .namesShouldMatch("regex"))) + .build() + .check(); +``` + +- **Controllers Configuration**: Ensure that controller classes end with "Controller" or match a specific regex pattern, are annotated with `@RestController`, do not depend on other controllers, and are package-private. + +```java +Taikai.builder() + .namespace("com.company.yourproject") + .spring(spring -> spring + .controllers(controllers -> controllers + .shouldBeAnnotatedWithRestController() + .namesShouldEndWithController() + .namesShouldMatch("regex") + .shouldNotDependOnOtherControllers() + .shouldBePackagePrivate())) + .build() + .check(); +``` + +- **Services Configuration**: Ensure that service classes end with "Service" or match a specific regex pattern and are annotated with `@Service`. + +```java +Taikai.builder() + .namespace("com.company.yourproject") + .spring(spring -> spring + .services(services -> services + .shouldBeAnnotatedWithService() + .namesShouldMatch("regex") + .namesShouldEndWithService())) + .build() + .check(); +``` + +- **Repositories Configuration**: Ensure that repository classes end with "Repository" or match a specific regex pattern and are annotated with `@Repository`. + +```java +Taikai.builder() + .namespace("com.company.yourproject") + .spring(spring -> spring + .repositories(repositories -> repositories + .shouldBeAnnotatedWithRepository() + .namesShouldMatch("regex") + .namesShouldEndWithRepository())) + .build() + .check(); +``` + +#### Examples + +Below are some examples demonstrating the usage of Taikai to define and enforce architectural rules in Java projects, including Spring-specific configurations: + +```java +class ArchitectureTest { + + @Test + void shouldFulfilConstrains() { + Taikai.builder() + .namespace("com.company.yourproject") + .test(test -> test + .junit5(junit5 -> junit5 + .classesShouldNotBeAnnotatedWithDisabled() + .methodsShouldNotBeAnnotatedWithDisabled())) + .java(java -> java + .noUsageOfDeprecatedAPIs() + .classesShouldImplementHashCodeAndEquals() + .methodsShouldNotThrowGenericException() + .utilityClassesShouldBeFinalAndHavePrivateConstructor()) + .spring(spring -> spring + .repositories(repositories -> repositories + .namesShouldEndWithRepository() + .shouldBeAnnotatedWithRepository()) + .services(services -> services + .namesShouldEndWithService() + .shouldBeAnnotatedWithService()) + .boot(boot -> boot + .shouldBeAnnotatedWithSpringBootApplication()) + .noAutowiredFields() + .configurations(configuration -> configuration + .namesShouldEndWithConfiguration() + .namesShouldMatch("regex")) + .controllers(controllers -> controllers + .shouldBeAnnotatedWithRestController() + .namesShouldEndWithController() + .namesShouldMatch("regex") + .shouldNotDependOnOtherControllers() + .shouldBePackagePrivate())) + .build() + .check(); + } +} +``` \ No newline at end of file