Nature of Architecture

All those architectures out there start as a simple consistent idea… and end in a mess. After too many change requests and refactoring tasks to improve your project or correct issues, there might be nothing much left of the architecture you once started with. In this post I will give an example on how to avoid such situations by writing unit tests to check and protect your architecture and the qualitiy of your project.

I already talked about Vaadin MVP on a few occasions

Lets use this architecture approach (MVP + CDI) for this post. One architecture question for all your big and long running projects should be:

How can I make sure all developers write their code according to the company’s architecture guideline?

Just as we (should) write unit tests to test our code, we can write tests to find out, if all the code fits to our architecture. ArchUnit is the framework that enables us to write such tests. To use ArchUnit in your maven project add these lines to your pom.xml:

<dependency>
	<groupId>com.tngtech.archunit</groupId>
	<artifactId>archunit-junit4</artifactId>
	<version>${archunit.version}</version>
	<scope>test</scope>
</dependency>

Gradle user can include the archunit library with

dependencies {
    testCompile 'com.tngtech.archunit:archunit:0.9.3'
}

Now let’s start with writing archtecture test. First we need to make clear what really are architectural rules we could test. In a Vaadin project we can (or should) use the MVP (model-view-presenter) architecture. Our domain (model) classes are placed in the my.app.model package. As we are having a JEE project all of our model classes should have the @javax.enterprise.inject.Model.Model annotation. Let’s write a test to make sure all classes have this annotation.

import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes;
import javax.enterprise.inject.Model;
import org.junit.Test;
import com.tngtech.archunit.core.domain.JavaClasses;
import com.tngtech.archunit.core.importer.ClassFileImporter;
import com.tngtech.archunit.lang.ArchRule;

/**
 * All model classes should have the @Model annotation.
 */
@Test
public void testModelClasses() {
	String modelPackage = "my.app.model";
	JavaClasses checkedClasses = new ClassFileImporter().importPackages(modelPackage);
	ArchRule rule = classes()
			.that()
			.resideInAPackage(modelPackage)
			.should()
			.beAnnotatedWith(Model.class);
	rule.check(checkedClasses);
}

As you can see ArchUnit gives us an almost readable fluent API to check our classes. The given code translates to

All classes that reside in the model package should be annotated with the @Model annotation.

Lets have another example. The presenter classes of a Vaadin MVP architecture should not be called from a model or a view class (there should not be code like new IndexPresenter() in your application). Here is the ArchUnit test code for this requirement that can be translated to:

All classes that reside in the presenter package should not be accessed from other packages.

/**
 * The presenter classes should be called by CDI events. No direct calls are allowed!
 */
@Test
public void servicesShouldOnlyBeAccessedByPresenters() {
	String presenterPackage = "my.app.presenter";
	JavaClasses checkedClasses = new ClassFileImporter().importPackages(presenterPackage);
	String [] accessors = {};
	ArchRule rule = classes()
			.that()
			.resideInAPackage(presenterPackage)
			.should()
			.onlyBeAccessed()
			.byAnyPackage(accessors);
	rule.check(checkedClasses);
}

These are just 2 small examples of what you can do with ArchUnit. I reallly think it is a useful tool for all medium and large projects where development teams from different departments of a company or from different companies create an application. Take a look at the user guide of ArchUnit for many more examples and use cases and – if you are really tired of writing unit tests – just remember that these tests should be coded by architects as it is their responsibility to check and protect their business architecture.

By Meik Kaufmann

I am a certified oracle enterprise architect and like to share my knowledge and experience that I gain in the projects I am working on.

Leave a Reply

Your email address will not be published. Required fields are marked *