Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.


Jira
serverONAP Jira
serverId425b2b0a-557c-3c0c-b515-579789cceedb
keyCPS-380


Introduction

We are implementing a testing library which will help improve architecture design within CPS-Core

Leading to

  • Less Complex Project Architecture
  • Easier Understanding of Architecture Layout for New Developers
  • Speed Up Overall Development


Problem Description

Existing architecture already exists for CPS-Core.

This can lead to issues when implementing dependency architecture rule tests such as:

Code Block
languagejava
themeMidnight
firstline39
titleDependencyArchitectureTest
linenumberstrue
    @ArchTest
    static final ArchRule noUpperPackageDependencyRule = NO_CLASSES_SHOULD_DEPEND_UPPER_PACKAGES;


The Purpose of this test is to prevent classes depending on other classes in upper packages. The purpose of this being that it "might prevent packages on that level from being split into artifacts in a clean way".

This has lead to the following error 

Code Block
languagebash
themeMidnight
java.lang.AssertionError: Architecture Violation [Priority: MEDIUM] - Rule 'no classes should depend on upper packages, because that might prevent packages on that level from being split into separate artifacts in a clean way' was violated (23 times)
Class <org.onap.cps.api.impl.CpsAdminServiceImpl> implements interface <org.onap.cps.api.CpsAdminService> in (CpsAdminServiceImpl.java:0)
Class <org.onap.cps.api.impl.CpsDataServiceImpl> implements interface <org.onap.cps.api.CpsDataService> in (CpsDataServiceImpl.java:0)
Class <org.onap.cps.api.impl.CpsModuleServiceImpl> implements interface <org.onap.cps.api.CpsModuleService> in (CpsModuleServiceImpl.java:0)
...


Proposal

This seems to be mostly happening in regard to the classes which lie in the impl packages one layer above the defined service interfaces. My proposed solution here would be to create a new package for the service interfaces. So both packages are on the same level, which would prevent this issue.

Similar to this:

Image Added


Problem Description.

Due to multiple packages existing in the cps-service module. It can lead to overly complicated architecture tests like this where the Spi services is accessed by 7 individual packages from 6 different layers

Code Block
languagejava
themeMidnight
firstline49
titleLayeredArchitectureTest
    @ArchTest
    static final ArchRule layeredArchitecturesRulesRespected = layeredArchitecture()
        .layer("Controller").definedBy(REST_CONTROLLER_PACKAGE)
        .layer("apiService").definedBy(API_SERVICE_PACKAGE)
        .layer("ncmpService").definedBy(NCMP_SERVICE_PACKAGE)
        .layer("Repository").definedBy(REPOSITORY_PACKAGE)
        .layer("spiService").definedBy(SPI_SERVICE_PACKAGE)
        .layer("ncmpController").definedBy(NCMP_REST_PACKAGE)
        .layer("yangSchema").definedBy(YANG_SCHEMA_PACKAGE)
        .layer("utils").definedBy(UTILS_PACKAGE)
        .whereLayer("Controller").mayNotBeAccessedByAnyLayer()
        .whereLayer("apiService").mayOnlyBeAccessedByLayers("Controller", "ncmpService")
        .whereLayer("spiService").mayOnlyBeAccessedByLayers("Controller", "apiService", "ncmpService", "ncmpController", "yangSchema", "utils")
        .whereLayer("Repository").mayOnlyBeAccessedByLayers("apiService", "spiService");


Code Block
languagejava
themeMidnight
firstline80
titleLayeredArchitectureTest
    @ArchTest
    static final ArchRule spiServiceDependencyRule =
        classes().that().resideInAPackage(SPI_SERVICE_PACKAGE).should().onlyHaveDependentClassesThat()
        .resideInAnyPackage(REST_CONTROLLER_PACKAGE, API_SERVICE_PACKAGE, SPI_SERVICE_PACKAGE,
            NCMP_SERVICE_PACKAGE, NCMP_REST_PACKAGE, UTILS_PACKAGE, YANG_SCHEMA_PACKAGE);

Whereas the Api Services are only accessed by the one rest controller package, being the cps rest controller, along the ncmp services rest, and it's own impl services.

Code Block
languagejava
themeMidnight
firstline71
titleLayeredArchitectureTest
    @ArchTest
    static final ArchRule apiServiceDependencyRule =
        classes().that().resideInAPackage(API_SERVICE_PACKAGE).should().onlyHaveDependentClassesThat()
        .resideInAnyPackage(REST_CONTROLLER_PACKAGE, API_SERVICE_PACKAGE, NCMP_SERVICE_PACKAGE);


Proposal

Adding another within the module package below the current services layer, containing these sub packages, similar to how rest module has a package below the controller and exceptions layer. This could lead to us covering both API and SPI services, along with the classes dependent on these services. In turn, cleaning up the project architecture in the process and simplifying these tests.

Example:

Code Block
languagejava
themeMidnight
firstline49
titleLayeredArchitectureTest
    @ArchTest
    static final ArchRule layeredArchitecturesRulesRespected = layeredArchitecture()
        .layer("Controller").definedBy(REST_CONTROLLER_PACKAGE)
        .layer("SERVICES").definedBy(SERVICES_PACKAGE)
        .layer("ncmpService").definedBy(NCMP_SERVICE_PACKAGE)
        .layer("Repository").definedBy(REPOSITORY_PACKAGE)
        .whereLayer("Controller").mayNotBeAccessedByAnyLayer()
        .whereLayer("Services").mayOnlyBeAccessedByLayers("Controller", "ncmpService")
        .whereLayer("Repository").mayOnlyBeAccessedByLayers("apiService", "spiService");


Code Block
languagejava
themeMidnight
    @ArchTest
    static final ArchRule apiServiceDependencyRule =
        classes().that().resideInAPackage(SERVICE_PACKAGES).should().onlyHaveDependentClassesThat()
        .resideInAnyPackage(REST_CONTROLLER_PACKAGE, NCMP_SERVICE_PACKAGE, NCMP_REST_PACKAGE,SERVICES_PACKAGE);

...