Introduction

Software architects have to make sure that the communicated software architecture blueprints exist in the real world. For this, manual inspections as well as automated measurements are needed to avoid surprises.

In this notebook, I want to show how software architects can define and check for architectural governance rules for Java applications using jQAssistant and Neo4j.

Idea

This notebook shows an approach to check for architectural rules using the structural code analyzer jQAssistant in combination with the graph database Neo4j. jQAssistant scans several artifacts (Java Bytecode, Git history, Maven Dependencies, and so on) and stores the structural information into the Neo4j database.

Figure 1: Overview of the analysis pipeline

Setup

If you want to execute the notebook, you also need to build the example project and run a Neo4j instance in the background. You can find the instructions here.

Load extension for querying the Neo4j graph database via Cypher.

In [1]:
%load_ext cypher

Define Concerns

In the application at hand (a fork of the Spring PetClinic project), there are Java classes called Entitys, that represent the database table. Each of these classes is marked by a special interface @Entity. We can find these classes by querying the graph database and create a higher level concern (or concept) to make further searches easier.

The following query defines Entitys and returns all found Entitys in the scanned codebase.

In [2]:
%%cypher
MATCH
  (t:Type)-[:ANNOTATED_BY]->()-[:OF_TYPE]->(a:Type)
WHERE
  a.fqn="javax.persistence.Entity"
SET
  t:Entity
RETURN
  t.fqn AS Entity
6 rows affected.
Out[2]:
Entity
org.springframework.samples.petclinic.repository.PetType
org.springframework.samples.petclinic.model.Vet
org.springframework.samples.petclinic.model.Specialty
org.springframework.samples.petclinic.model.Visit
org.springframework.samples.petclinic.model.Pet
org.springframework.samples.petclinic.model.Owner

Rule Definition

Because we want to enable developers to quickly identify Entities in the application, we use the Java package names to define were all the Entities are placed. Thus, Entities must be placed in a package named model.

The following query lists all existing Entities in the scanned codebase:

In [3]:
%%cypher
MATCH (e:Entity)<-[:CONTAINS]-(p:Package)
WHERE p.name = "model"
RETURN e.fqn as Entity, p.name as Package
5 rows affected.
Out[3]:
Entity Package
org.springframework.samples.petclinic.model.Owner model
org.springframework.samples.petclinic.model.Pet model
org.springframework.samples.petclinic.model.Visit model
org.springframework.samples.petclinic.model.Specialty model
org.springframework.samples.petclinic.model.Vet model

Rule Violations

The following query lists all Enties that doesn't comply to the rule above:

In [4]:
%%cypher
MATCH (e:Entity)<-[:CONTAINS]-(p:Package)
WHERE p.name <> "model"
RETURN e.fqn as MisplacedEntity, p.name as WrongPackage
1 rows affected.
Out[4]:
MisplacedEntity WrongPackage
org.springframework.samples.petclinic.repository.PetType repository