I'm working on a Java project where we have a specific requirement: all BigDecimal instances should be created exclusively through a utility class, let's call it MathUtils. The goal is to ensure consistent application of a MathContext and other configurations.
To enforce this rule across our codebase, I am looking into using ArchUnit. However, I'm facing challenges in formulating a rule that ensures BigDecimal is only instantiated within MathUtils and not directly in other parts of the application.
Here's what I've tried so far:
@ArchTest
public static final ArchRule bigDecimalShouldOnlyBeInstantiatedInMathUtils = noClasses()
.that().doNotHaveFullyQualifiedName("a.b.c.MathUtils")
.should().callConstructor(BigDecimal.class)
.because("BigDecimal should only be instantiated in MathUtils");
I am looking for guidance on how to properly set up an ArchUnit rule for this purpose, or if there's another approach or tool I should consider for enforcing such architectural constraints in Java.
Key Points:
- How to write an ArchUnit rule to ensure BigDecimal instances are only created in a specific class (MathUtils)?
- Are there alternative strategies or tools in Java for enforcing this kind of architectural rule?
Any insights or suggestions would be greatly appreciated!
In my opinion, it is a good idea to use ArchUnit to check wanted / unwanted dependencies between Java classes. Another alternative would be jQAssistant.
For your specific requirement, 2 more things need to be considered:
callConstructor(BigDecimal.class)only checks for calls to the no-args constructor, because the method is actually defined ascallConstructor(Class<?> owner, Class<?>... parameterTypes)valueOfmethods, where I assume that these calls are also not wanted.Considering these 2 aspects, you could write this rule:
Note that I changed
.because(..)to.as(..)to create a shorter rule description for error messages, because the original one may be too verbose.