文档章节

代码质量之Archunit的使用

克虏伯
 克虏伯
发布于 09/14 23:54
字数 962
阅读 101
收藏 0

    注:开发的编辑器: Intellij Idea,JDK版本是JDK8

    Archunit是什么,官网的英文介绍很好,建议阅读原文,"ArchUnit is a free, simple and extensible library for checking the architecture of your Java code using any plain Java unit test framework. That is, ArchUnit can check dependencies between packages and classes, layers and slices, check for cyclic dependencies and more"。

    简单来说,它是代码格式、类之间的依赖关系检查工具。

  1. 进入官网
  2. 点击右上角的"User Gruide"
  3. 之后就可以看到它的英文教程文档。

1.pom.xml中加入依赖

    List-1 最重要的是archunit-junit4依赖

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>com.tngtech.archunit</groupId>
    <artifactId>archunit-junit4</artifactId>
    <version>0.9.1</version>
    <scope>test</scope>
</dependency>

2.添加规则

    直接上代码了,如下List-2所示,按项目情况,修改自己的"@AnalyzeClasses的packages值"

    List-2

import javax.persistence.Entity;

import com.tngtech.archunit.junit.AnalyzeClasses;
import com.tngtech.archunit.junit.ArchTest;
import com.tngtech.archunit.junit.ArchUnitRunner;
import com.tngtech.archunit.lang.ArchRule;

import org.junit.runner.RunWith;

import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;
import static com.tngtech.archunit.library.GeneralCodingRules.NO_CLASSES_SHOULD_ACCESS_STANDARD_STREAMS;
import static com.tngtech.archunit.library.GeneralCodingRules.NO_CLASSES_SHOULD_THROW_GENERIC_EXCEPTIONS;
import static com.tngtech.archunit.library.GeneralCodingRules.NO_CLASSES_SHOULD_USE_JAVA_UTIL_LOGGING;

/**
 * @author dmj1161859184@126.com 2018-09-14 23:03
 * @version 1.0
 * @since 1.0
 */
@RunWith(ArchUnitRunner.class) // Remove this line for JUnit 5!!
@AnalyzeClasses(packages = "com.mjduan.project") //要扫描的package
public class ArchunitTest {

    /** dao下的类应该以Dao结尾 */
    @ArchTest
    public static final ArchRule DAOs_must_reside_in_a_dao_package = classes()
            .that()
            .haveNameMatching(".*Dao")
            .should()
            .resideInAPackage("..dao..")
            .as("DAOs should reside in a package '..dao..'");

    /** controller下的类应该以Controller结尾 */
    @ArchTest
    public static final ArchRule CONTROLLERs_must_reside_in_a_dao_package = classes()
            .that()
            .haveNameMatching(".*Controller")
            .should()
            .resideInAPackage("..controller..")
            .as("DAOs should reside in a package '..dao..'");

    /** util下的类应该以Util结尾 */
    @ArchTest
    public static final ArchRule UTILs_must_reside_in_a_dao_package = classes()
            .that()
            .haveNameMatching(".*Util")
            .should()
            .resideInAPackage("..util..")
            .as("DAOs should reside in a package '..dao..'");

    /** 有Entity注解的类,应该在domain或者entity包下 */
    @ArchTest
    public static final ArchRule entities_must_reside_in_a_domain_package = classes()
            .that()
            .areAnnotatedWith(Entity.class)
            .should()
            .resideInAnyPackage("..domain..", "..entity..");

    /** 接口类,应该以I开头 */
    @ArchTest
    public static final ArchRule interface_className_must_start_with_I = classes()
            .that()
            .areInterfaces()
            .should()
            .haveSimpleNameStartingWith("I")
            .as("Interface should start with I");

    /** service下的类,只能被controller下或者时service下的类访问 */
    @ArchTest
    public static final ArchRule services_should_only_be_accessed_by_controllers_or_other_services = classes()
            .that()
            .resideInAPackage("..service..")
            .should()
            .onlyBeAccessed()
            .byAnyPackage("..controller..", "..service..");
    /** impl下的类,不能是interface */
    @ArchTest
    public static final ArchRule interfaces_must_not_be_placed_in_implementation_packages = noClasses()
            .that()
            .resideInAPackage("..impl..")
            .should()
            .beInterfaces();
    /** 接口类,类名不能以Interface结尾 */
    @ArchTest
    public static final ArchRule interfaces_should_not_have_names_ending_with_the_word_interface = noClasses()
            .that()
            .areInterfaces()
            .should()
            .haveNameMatching(".*Interface");
    /** service下的类,不能调用controller下的类 */
    @ArchTest
    public static final ArchRule services_should_not_access_controllers = noClasses()
            .that()
            .resideInAPackage("..service..")
            .should()
            .accessClassesThat()
            .resideInAPackage("..controller..");
    /** dao下的类,不能调用controller下的类 */
    @ArchTest
    public static final ArchRule controllers_should_not_access_dao = noClasses()
            .that()
            .resideInAPackage("..dao..")
            .should()
            .accessClassesThat()
            .resideInAnyPackage("..controller..");
    /** 不应该使用System.* */
    @ArchTest
    private final ArchRule NO_ACCESS_TO_STANDARD_STREAMS = NO_CLASSES_SHOULD_ACCESS_STANDARD_STREAMS;
    /** 不应该抛出Exception */
    @ArchTest
    private final ArchRule NO_GENERIC_EXCEPTIONS = NO_CLASSES_SHOULD_THROW_GENERIC_EXCEPTIONS;
    /** 不应该使用java.util.logging来记录日志 */
    @ArchTest
    private final ArchRule NO_JAVA_UTIL_LOGGING = NO_CLASSES_SHOULD_USE_JAVA_UTIL_LOGGING;
}

    List-2中的代码中已经给出注释,自己可以在项目中运行看下结果。不过发现有个不好的地方是,archunit会扫描test下的类。

    注:如果要忽略某个规则,那么加上@ArchIgnore就可以了,参考这里

2.1 忽略某个规则

    List-3

public class ArchitectureTest {

    // will run
    @ArchTest
    public static final ArchRule rule1 = classes().should()...

    // won't run
    @ArchIgnore
    @ArchTest
    public static final ArchRule rule2 = classes().should()...
}

2.2 忽略多个类,即不让Archunit扫描多个类

    一般出现在遗留系统中。

                     

                                                            图2.1 

    比如我们想在Archunit扫描时,忽略DemoInterface和AnnotationDemo,那么在resources下建个"archunit_ignore_patterns.txt"的文件(这个文件名称是固定的,不能修改),在将要忽略的类路径放入其中,注意格式,如下图2.2所示,参考其官网

    

                                                            图2.2

3.Demo

    新建一个interface,名为DemoInterface,之后运行List-2,结果如下图1所示,由于DemoInterface是interface,类名以Interface结尾(List-2中定义不能以Interface结尾),未以I开头(List-2中定义要以I开头):

                                                    图3.1  运行List-2后报错信息

4.官方的Archunit example

    可以在Github上看Archunit的例子,Github地址: https://github.com/TNG/ArchUnit-Examples    

    实际项目中,代码量较多,规范要做好,特别是人员流动是公司中很常见的。

© 著作权归作者所有

共有 人打赏支持
上一篇: 破解Intellij Idea
下一篇: Front之vue
克虏伯

克虏伯

粉丝 15
博文 318
码字总数 106998
作品 0
渝北
程序员
私信 提问
雷达哔哔哔 - #3-Architectural fitness function

1. 推荐度: TRIAL[ 2017.11 | 2018.05 ] 2. 所属象限: Techniques 3. 关注问题: 技术架构腐化带来的系统响应度降低,可维护性下降,技术债缠身。 而盲目优化或是单纯的技术驱动的架构优化...

王健_TW
09/21
0
0
代码质量与规范,那些年你欠下的技术债

欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文来自云+社区专栏,作者腾讯移动品质中心TMQ 提到“质量”二字时,我们的第一反应往往是“有多少BUG?”“性能好不好?“这样...

腾讯云加社区
07/03
0
0
Jenkins 2.x(Pipeline),SonarQube 和 Artifactory 搭建持续交付流水线

持续交付和 DevOps 是众所周知的,并在当今广泛传播的做法。人们普遍认为,组建优秀的团队,首先确定共同的目标,然后选择和整合最适合的工具是至关重要的。通常,这是一个轻量级工具的集合,...

JFrog中国
2017/11/16
0
0
SonarQube代码质量分析平台介绍

1.使用需求 随着互联网产品迭代越来越快,客户对产品的要求也越来越高,因此如何高质量的交付代码,及时地对代码质量进行分析并给出合理的解决方案就成为了当下必须要解决的一个问题。Sonar...

江边望海
2015/07/15
0
0
【转载】【面试题】你是一个测试工程师,如何保证软件质量?

参答*案:质量是有层次(内部质量,外部质量,使用质量,过程质量) 内部质量:主要指代码的质量,就需要引入开发工程师进行单元测试。 外部质量:软件被整合成为一个整体,从整体上保证软件...

beijing_zbs
2016/04/21
621
0

没有更多内容

加载失败,请刷新页面

加载更多

Windows 环境下安装 Oracle JDK

本页面中描述了如何在 Window 环境下安装 Oracle JDK。 我们使用的版本是 Window 10,我们需要安装的版本是 Oracle JDK 8u191。 检查当前版本 在进行新的 JDK 安装之前,你需要检查下你本地的...

honeymose
13分钟前
0
0
用any-loader封装jQuery的XHR —— 随便写着玩系列

哎,都说没人用JQuery啦,叫你别写这个。 其实我也是好高骛远使用过npm上某个和某个很出名的XHR库,嗯,认识我的人都知道我喜欢喷JQ,以前天天喷,见面第一句,你还用JQ,赶紧丢了吧。但我也...

曾建凯
今天
4
0
聊聊storm的AggregateProcessor的execute及finishBatch方法

序 本文主要研究一下storm的AggregateProcessor的execute及finishBatch方法 实例 TridentTopology topology = new TridentTopology(); topology.newStream("spout1", spout......

go4it
今天
3
0
大数据教程(7.5)hadoop中内置rpc框架的使用教程

博主上一篇博客分享了hadoop客户端java API的使用,本章节带领小伙伴们一起来体验下hadoop的内置rpc框架。首先,由于hadoop的内置rpc框架的设计目的是为了内部的组件提供rpc访问的功能,并不...

em_aaron
今天
5
0
CentOS7+git+github创建Python开发环境

1.准备CentOS7 (1)下载VMware Workstation https://pan.baidu.com/s/1miFU8mk (2)下载CentOS7镜像 https://mirrors.aliyun.com/centos/ (3)安装CentOS7系统 http://blog.51cto.com/fengyuns......

枫叶云
昨天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部