Enhancing Software Governance and Quality With jMolecules: Fighting Software Erosion
jMolecules uses annotations to enforce architectural rules, prevent software erosion, and simplify validation with tools like ArchUnit. It supports DDD, CQRS, and more.
Join the DZone community and get the full member experience.
Join For FreeSoftware erosion — gradual decay in software quality due to unmanaged technical debt and architectural drift — is a persistent challenge in software development. To combat this, jMolecules emerges as a robust, annotation-driven framework that simplifies the expression and enforcement of architectural principles within your codebase. By explicitly defining architectural concepts, jMolecules facilitates governance, quality assurance, and architectural integrity, ensuring your software remains robust.
In this article, we'll explore jMolecules's fundamentals, its benefits, and a practical example of integrating it with ArchUnit to enforce Domain-Driven Design (DDD) principles. For further details, you can visit the jMolecules GitHub repository.
Why jMolecules?
jMolecules provides developers with annotations that make architectural evidence explicit in the code, ensuring clarity and structure. It achieves this through:
- Expressive Code: Architectural concepts are explicitly represented, aiding in code readability and maintainability.
- Domain Isolation: Domain-specific code remains free from technical dependencies.
- Boilerplate Reduction: Simplifies repetitive tasks, enabling developers to focus on logic.
- Tool Integration:
- Augmenting code with tools like ByteBuddy for Spring and JPA integration.
- Enforcing architectural rules with tools like ArchUnit and jQAssistant.
- Documentation Generation: Automatically generates architectural documentation and validates implementation.
Modular Design for Flexibility
jMolecules provides modules tailored to different architectural styles, allowing developers to adapt the framework to their needs. Some notable modules include:
- jmolecules-cqrs-architecture: For Command-Query Responsibility Segregation (CQRS).
- jmolecules-layered-architecture: For traditional layered architectures.
- jmolecules-onion-architecture: For Onion architecture.
- jmolecules-hexagonal-architecture: For Hexagonal architecture.
- jmolecules-ddd: This defines DDD building blocks like entities, value objects, and aggregates.
- jmolecules-events: For representing domain events.
A Practical Example: Ensuring DDD Compliance With ArchUnit
Defining a Domain Entity
Let's start by defining a simple domain entity — a credit card. Using the @Entity
annotation from jMolecules, we define our entity as follows:
@Entity
public class CreditCard {
private BigInteger id;
private String number;
private String name;
private YearMonth expiry;
}
Validating DDD Compliance
To ensure the entity adheres to DDD principles, we can use jMolecules with ArchUnit. There are two approaches: manual validation and annotation-driven validation.
Manual Validation
public class JMoleculesDddUnitTest {
@Test
void checkTheLayerIntegration() {
String packageName = "expert.os.examples";
JavaClasses classes = new ClassFileImporter().importPackages(packageName);
JMoleculesArchitectureRules.ensureLayering().check(classes);
}
@Test
void checkDDDIntegration() {
String packageName = "expert.os.examples";
JavaClasses classes = new ClassFileImporter().importPackages(packageName);
JMoleculesDddRules.all().check(classes);
}
}
Annotation-Driven Validation
The integration becomes more concise with annotations:
@AnalyzeClasses(packages = "expert.os.examples")
public class IntegrationSampleTest {
@ArchTest
private ArchRule dddRules = JMoleculesDddRules.all();
@ArchTest
private ArchRule layering = JMoleculesArchitectureRules.ensureLayering();
@ArchTest
void detectsViolations(JavaClasses classes) {
EvaluationResult result = JMoleculesDddRules.all().evaluate(classes);
assertThat(result.hasViolation()).isFalse();
}
}
Running the tests may reveal violations, such as:
Type e.o.e.CreditCard must declare a field or a method annotated with org.jmolecules.ddd.annotation.Identity!
This error aligns with Eric Evans' DDD definition of an entity, emphasizing the importance of identity. To resolve this, we annotate the id field with @Identity
:
@Entity
public class CreditCard {
@Identity
private BigInteger id;
private String number;
private String name;
private YearMonth expiry;
}
With this adjustment, the tests pass, ensuring our entity adheres to DDD principles.
Conclusion
jMolecules offers a comprehensive suite of validations and tools that are invaluable in real-world projects. While this article briefly introduces the framework's capabilities extend far beyond the scope covered here. Explore the project repository to dive deeper into jMolecules and its integration.
By leveraging jMolecules, developers can effectively combat software erosion, maintain architectural integrity, and build high-quality, sustainable software systems.
Video
Opinions expressed by DZone contributors are their own.
Comments