跟ApacheBeam学质量控制之道

简介: 在学习、开发Apache Beam源码过程中,除了它精妙的设计(通过几个简单的概念抽象把实时和离线的计算逻辑模型统一了起来),庞大的代码量(Java 33万行, Python9万行),还有一个比较大的感受是它的质量控制做得特别好,比之前参与过的其它一些开源项目都要好,这可能跟Google的工程质量高于业界有关。但是这里面也没什么什么奇技淫巧,只是善用了一些插件而已,我在这里想把我在Apache B

在学习、开发Apache Beam源码过程中,除了它精妙的设计(通过几个简单的概念抽象把实时和离线的计算逻辑模型统一了起来),庞大的代码量(Java 33万行, Python9万行),还有一个比较大的感受是它的质量控制做得特别好,比之前参与过的其它一些开源项目都要好,这可能跟Google的工程质量高于业界有关。但是这里面也没什么什么奇技淫巧,只是善用了一些插件而已,我在这里想把我在Apache Beam里面看到、学到的一些质量实践分享给大家。代码质量提升其实没有什么太多的捷径,这里要分享的也不是多么高大上的道理,每个小点都是很零碎的一个小技巧,但是所有这些小技巧组合起来,会让你对代码的质量更有信心。

我们代码里面的一些常见问题

事物的好坏是对比出来的,我们先来看看我们代码里面一些问题。

随意的JavaDoc

比如:

/**
 * UserService
 *
 * @author <somebody>
 * @version $Id: UserService.java, v 0.1 2014年8月28日 上午11:04:58 <somebody> Exp $
 */
public interface UserService extends ExtUserService {

再比如:

/**
 * DataProjectService
 *
 * @author <somebody>
 * @since created on 2015-10-28 22:27
 */
public interface DataProjectService {

我们代码很多没有javadoc, 或者好一点的有javadoc,但是不符合javadoc规范(用javadoc实际去生成会报格式不对)。

超长的代码

下面截取一段CAP里面的代码:

    /**
     * // 看这里
     * @see com.alipay.cap.core.service.DataProjectAccessKeyService#updateExcuteAKById(java.lang.Long, java.lang.String, java.lang.String)
     */
    @Override
    public void updateExcuteAKByUnionKey(String namespaceId, String dataProjectKey, String accessId, String accessKey, String operator) {
        CapNamespaceProjectAkCriteria example = new CapNamespaceProjectAkCriteria();
        example.createCriteria()
            .andDataProjectKeyEqualTo(dataProjectKey)
            .andNamespaceIdEqualTo(namespaceId)
            .andIsDeletedEqualTo(false);
        List<CapNamespaceProjectAkDO> capNamespaceProjectAkDOs = capNamespaceProjectAkDAO.selectByExample(example);
        // .....
    }

比如这里这行代码长达138,与一般的推荐配置(80, 最多100)长多了,已经超出一屏了,看起来很难受。

重复的、未使用的maven依赖

用依赖分析工具分析一下CAP的代码依赖,可以发现,里面有很多没用的依赖以及用到了但是没有声明的依赖。

[INFO] --- maven-dependency-plugin:2.8:analyze (default-cli) @ cap-web-openapi ---
[WARNING] Used undeclared dependencies found:
[WARNING]    com.alipay.cap:cap-common-client:jar:1.0.20140703:compile
[WARNING]    com.alipay.cap:cap-common-conf-core:jar:1.0.20170512:compile
[WARNING]    com.alipay.cap:cap-common-dal:jar:1.1:compile
[WARNING]    com.google.code.findbugs:annotations:jar:2.0.3:compile
[WARNING]    com.alibaba.alimonitor:alimonitor-jmonitor:jar:1.0.4:compile
[WARNING]    org.slf4j:slf4j-api:jar:1.7.14:compile
[WARNING]    com.alipay.dpc:smartmw-cache:jar:2.0.20161227:compile
[WARNING]    org.springframework:org.springframework.context:jar:3.0.5.RELEASE:compile
[WARNING]    org.springframework:spring-modules-validation:jar:0.9:compile
[WARNING]    org.springframework:org.springframework.core:jar:3.0.5.RELEASE:compile
[WARNING]    com.alibaba:fastjson:jar:1.2.8.sec01:compile
[WARNING]    com.alibaba.toolkit.common:toolkit-common-lang:jar:1.1.1:compile
[WARNING]    com.alipay.sofa:sofa-runtime-api:jar:4.5.2:compile
[WARNING] Unused declared dependencies found:
[WARNING]    com.alipay.sofa.service:sofa-service-api:jar:3.2.4.1:compile
[WARNING]    com.alipay.sofa.web.mvc:mvc-sofa-env-plugin:jar:4.1.6:compile
[WARNING]    com.alipay.sofa.web.mvc:mvc-alipay-toolbox-plugin:jar:4.1.6:compile
[WARNING]    com.alipay.sofa.web.mvc:mvc-toolbox-plugin:jar:4.1.6:compile
[WARNING]    com.alipay.sofa.web.mvc:mvc-validation-plugin:jar:4.1.6:compile
[WARNING]    com.alipay.sofa.web.mvc:mvc-tair-session-plugin:jar:4.1.6:compile
[WARNING]    com.alipay.sofa.web.mvc:mvc-widget-plugin:jar:4.1.6:compile
[WARNING]    com.alipay.sofa.web.mvc:mvc-uisvr-plugin:jar:4.1.6:compile
[WARNING]    com.alipay.sofa.web.mvc:mvc-json-plugin:jar:4.1.6:compile
[WARNING]    com.alipay.sofa.web.mvc:mvc-resource-plugin:jar:4.1.6:compile
[WARNING]    com.alipay.sofa.web.mvc:mvc-alipay-security-plugin:jar:4.1.6:compile
[WARNING]    com.alipay.sofa.web.mvc:mvc-alipay-auth-plugin:jar:4.1.6:compile
[WARNING]    commons-beanutils:commons-beanutils:jar:1.7.0:compile
[WARNING]    com.alipay.cap:cap-biz-service-impl:jar:1.0:compile
[WARNING]    org.springframework:spring-webmvc:jar:3.2.2:compile

这些每个问题单个看起来都不是大问题,但是堆积起来会让代码看起来有点

Beam里面的一些小实践

下面我介绍一下我在Beam里面看到的质量控制相关的一些小技巧,主要是一些maven插件的使用和一些测试库的使用,以及一些思想上的意识。

Dependency插件

Dependency插件的作用是帮我们扫描项目的依赖问题,它可以把我们实际要到了,但是没有声明的依赖;或者实际没用到,但是声明了的依赖都给找出来,帮你保持代码的纯洁, 下面是一个扫描报错的例子:

[INFO] --- maven-dependency-plugin:3.0.1:analyze-only (default) @ beam-dsls-sql ---
[WARNING] Unused declared dependencies found:
[WARNING]    com.google.auto.value:auto-value:jar:1.4.1:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 27.409 s
[INFO] Finished at: 2017-06-16T11:33:03+08:00
[INFO] Final Memory: 50M/401M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-dependency-plugin:3.0.1:analyze-only (default) on project beam-dsls-sql: Dependency problems found -> [Help 1]
[ERROR]

这里我们声明了一个没有用到的,但是声明了的auto-value的依赖,因此编译失败了。有了这个插件的保证,我们可以很有自信的知道我们引入的每个依赖都是有用的,有意义的。

Checkstyle

Checkstyle is a development tool to help programmers write Java code that adheres to a coding standard. It automates the process of checking Java code to spare humans of this boring (but important) task. This makes it ideal for projects that want to enforce a coding standard.

它能做的一些典型检查包括:

  • FallThrough: 如果你的switch/case里面没有写break,它会自动检测出来。
  • CustomImportOrder: 检查import的顺序符合指定样式。
  • LineLength: 检查代码行数不要超长。
  • MethodLength: 检查方法行数不要超长。

下面是我最近在写Beam代码的时候编译时候报的几个Checkstyle错误:

[bash] There are 5 errors reported by Checkstyle 6.19 with beam/checkstyle.xml ruleset.
[ERROR] src/main/java/org/apache/beam/dsls/sql/meta/Column.java:[19](javadoc) JavadocType: Missing a Javadoc comment.
[ERROR] src/main/java/org/apache/beam/dsls/sql/meta/DefaultMetaStore.java:[9](javadoc) JavadocParagraph: Empty line should be followed by <p> tag on the next line.
[ERROR] src/main/java/org/apache/beam/dsls/sql/meta/Table.java:[21](javadoc) JavadocType: Missing a Javadoc comment.
[ERROR] src/main/java/org/apache/beam/dsls/sql/meta/Table.java:[35](javadoc) JavadocParagraph: Empty line should be followed by <p> tag on the next line.
[ERROR] src/main/java/org/apache/beam/dsls/sql/rel/BeamValuesRel.java:[60](sizes) LineLength: Line is longer than 100 characters (found 115).
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 27.517 s
[INFO] Finished at: 2017-06-19T14:49:28+08:00
[INFO] Final Memory: 49M/478M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-checkstyle-plugin:2.17:check (default) on project beam-dsls-sql: You have 5 Checkstyle violations. -> [Help 1]

Enforcer插件

Enforcer是另一比有意思的maven插件, 它可以帮你指定你代码所需的运行环境,比如需要的maven版本(maven不同版本之间有时候行为差异还是很大的,比如我们采云间的代码基本都是用3.x版本编译的,但是开发机上默认装的是2.x的,这样编译的时候就会报很奇怪的错误,而enforcer插件则可以把这个需求明确化,如果你的maven的版本不对,它会明确告诉你maven版本不对,而不是其它的诡异错误)。它能做到的一些检查包括:

  • Maven的版本
  • JDK的版本
  • OS的版本
  • 检查指定的属性(property)是否存在

在我看来maven-enforcer-plugin有点像java语言里面assert,assert如果失败了,说明运行环境有问题,直接失败。

下面是一个Maven版本不对的错误:

[INFO] --- maven-enforcer-plugin:1.4.1:enforce (enforce) @ beam-dsls-sql ---
[WARNING] Rule 2: org.apache.maven.plugins.enforcer.RequireMavenVersion failed with message:
Detected Maven Version: 3.1.1 is not in the allowed range [3.2,).

Google AutoValue

最近这些年函数式编程的思维开始流行起来,很多非函数式的语言也开始在语言层面支持某些函数式的特征,比如Java 8里面的lambda, stream等等,Google AutoValue也是类似的目的,它的目的是让你的POJO编程readonly的(只有Getter), 从而实现函数式语言里面Immutable的特性。

它最大的贡献在于,它让你只需要定义你需要的字段:

import com.google.auto.value.AutoValue;

@AutoValue
abstract class Animal {
  static Animal create(String name, int numberOfLegs) {
    // See "How do I...?" below for nested classes.
    return new AutoValue_Animal(name, numberOfLegs);
  }

  abstract String name();
  abstract int numberOfLegs();
}

这里我们定义了我们需要两个字段: namenumberOfLegs以及一个用来构建Animal对象的create方法,其它的则都由AutoValue自动生成,其中AutoValue_Animal就是AutoValue自动生成的类。在AutoValue_Animal里面,它帮我们自动实现了hashCode, equals, toString等等这些重要的方法。这些方法的特征是实现的过程基本都一样,但是容易出错(由于粗心), 那么不如交给框架去自动产生。

如果你的类字段比较多,那么AutoValue还支持Builder模式:

import com.google.auto.value.AutoValue;

@AutoValue
abstract class Animal {
  abstract String name();
  abstract int numberOfLegs();

  static Builder builder() {
    return new AutoValue_Animal.Builder();
  }

  @AutoValue.Builder
  abstract static class Builder {
    abstract Builder setName(String value);
    abstract Builder setNumberOfLegs(int value);
    abstract Animal build();
  }
}

这样我们就可以一步一步渐进地把对象构造出来了。

Api Surface Test

所谓的API Surface是指我们一个系统暴露给另外一个系统一个SDK的时候,我们到底应该把哪些类,哪些package暴露给用户,这个问题很重要,因为考虑向后兼容性的话,暴露的package越少,将来修改的时候,破坏向后兼容性的可能性就越小,SDK就越稳定。我们平常的时候对于这种事情可能都是通过人肉分析、review,在Beam里面它直接编写成了一个单元测试:

  @Test
  public void testSdkApiSurface() throws Exception {

    @SuppressWarnings("unchecked")
    final Set<String> allowed =
        ImmutableSet.of(
            "org.apache.beam",
            "com.fasterxml.jackson.annotation",
            "com.fasterxml.jackson.core",
            "com.fasterxml.jackson.databind",
            "org.apache.avro",
            "org.hamcrest",
            // via DataflowMatchers
            "org.codehaus.jackson",
            // via Avro
            "org.joda.time",
            "org.junit");

    assertThat(
        ApiSurface.getSdkApiSurface(getClass().getClassLoader()), containsOnlyPackages(allowed));
  }

这个测试表明,Beam的SDK向外暴露的package就是上面列出的这些,下次来个新手贡献的代码如果破坏了这个约定,那么这个单元测试就直接报错,无法提交merge。还是那句话,凡是能自动化检测的东西不要依靠人肉。这里涉及到的主要技术是:

  1. 通过扫描classpath对指定包里面所有类的方法,参数,返回值进行检查。
  2. hamcrest这个支持matcher的单元测试的库,它让你不只可以assertTrue, assertFalse, assertEquals, 而是可以自由指定需要满足的条件。

总结

给Beam贡献代码的时候最大感受在于,你不需要去问其它Commiter或者看什么文档去确认你的代码风格是否符合,是否用对了Maven版本,JDK的版本对不对,JavaDoc需不需要写等等,你只要编译下代码,maven会告诉你的代码是否OK。只要通过了编译,代码风格、一些小的错误等等基本不会有了,那么代码review的时候主要就集中在代码设计层面了。有用的maven插件还有很多,这里只是举了几个例子,我觉得比每个插件本身更重要的是:

  1. 对代码质量的重视的意识。
  2. 使用工具/代码(而不是文档、流程)来解决保障代码质量。
目录
相关文章
|
1月前
|
敏捷开发 安全 测试技术
软件测试的艺术:确保质量与性能的平衡之道
【9月更文挑战第24天】在软件开发的海洋中,测试是导航灯塔,指引着项目安全抵达质量的彼岸。本文将深入探讨软件测试的核心原则、方法论以及如何通过精心设计的测试策略来保障产品的可靠性和性能。我们将从测试的基础知识出发,逐步深入到高级测试技巧,最终展示如何通过实际案例来应用这些知识以确保软件的成功交付。
|
1月前
|
测试技术 Python
软件测试的艺术:确保质量与性能
【9月更文挑战第19天】在数字化时代,软件已成为我们生活的一部分。然而,随着软件复杂性的增加,如何确保其质量和性能成为了一个挑战。本文将探讨软件测试的重要性,介绍常见的测试类型和策略,并提供实用的代码示例来帮助读者更好地理解和应用这些测试方法。无论你是开发人员、测试工程师还是项目管理者,这篇文章都将为你提供有价值的见解和技巧。
|
1月前
|
测试技术 UED 开发者
软件测试的艺术:从代码审查到用户反馈的全景探索在软件开发的宇宙中,测试是那颗确保星系正常运转的暗物质。它或许不总是站在聚光灯下,但无疑是支撑整个系统稳定性与可靠性的基石。《软件测试的艺术:从代码审查到用户反馈的全景探索》一文,旨在揭开软件测试这一神秘面纱,通过深入浅出的方式,引领读者穿梭于测试的各个环节,从细微处着眼,至宏观视角俯瞰,全方位解析如何打造无懈可击的软件产品。
本文以“软件测试的艺术”为核心,创新性地将技术深度与通俗易懂的语言风格相结合,绘制了一幅从代码审查到用户反馈全过程的测试蓝图。不同于常规摘要的枯燥概述,这里更像是一段旅程的预告片,承诺带领读者经历一场从微观世界到宏观视野的探索之旅,揭示每一个测试环节背后的哲学与实践智慧,让即便是非专业人士也能领略到软件测试的魅力所在,并从中获取实用的启示。
|
2月前
|
监控 测试技术 UED
软件测试的艺术:确保质量的五个关键实践
【8月更文挑战第28天】 在软件开发领域,测试不仅是发现错误的工具,更是确保产品稳定性、性能和用户满意度的基石。本文将深入探讨五个关键的软件测试实践,包括单元测试、集成测试、系统测试、压力测试和回归测试,以及它们如何共同构建起一个坚实的质量保证体系。通过这些实践,我们不仅能够提升软件的质量,还能更好地预测和应对潜在的风险,从而为最终用户提供更加稳定可靠的软件产品。
52 5
|
2月前
质量标准化实践问题之功能预演中出现问题如何解决
质量标准化实践问题之功能预演中出现问题如何解决
18 1
|
2月前
|
测试技术
软件测试的艺术与实践:确保质量的五步法
在数字化时代的浪潮中,软件成为了我们日常生活和工作中不可或缺的一部分。高质量的软件产品能够为用户提供流畅的体验,而软件测试是确保产品质量的关键步骤。本文将介绍一种简洁高效的软件测试方法—“五步法”,旨在帮助读者理解如何通过结构化的测试流程来提升软件的可靠性和性能。从需求分析到用户接受度测试,每一步都承载着其独特的价值和意义,共同构建起一道坚固的质量防线。让我们一起探索这门艺术和科学的结合体,揭开软件测试的神秘面纱。
53 1
|
2月前
|
测试技术 持续交付
软件测试的艺术:确保质量的探索之旅
在数字化时代的浪潮中,软件成为我们生活和工作不可或缺的一部分。但在这背后,隐藏着一个不为人知的世界——软件测试。它如同一位默默无闻的守护者,确保每一个程序的稳定性、可靠性与性能。本文将带您走进软件测试的核心,揭示它的重要性,探索不同的测试方法,并分享如何通过持续集成和自动化测试提升效率。让我们一同踏上这场确保软件质量的探索之旅,发现那些让软件变得更加完美的秘诀吧!
|
2月前
|
敏捷开发 安全 测试技术
软件测试的艺术:确保质量的不二法门
【8月更文挑战第8天】在软件开发的海洋中,测试是指引航船安全前行的灯塔。本文将深入探索软件测试的核心价值和实施策略,揭示其对保障产品质量的重要性。通过分析测试流程、测试人员的角色以及面临的挑战,我们将展现如何在不断变化的技术环境中保持测试活动的有效性和前瞻性。
30 0
|
5月前
|
敏捷开发 Devops 测试技术
深入探索软件测试:保障质量的终极策略
【4月更文挑战第18天】在软件开发生命周期中,确保最终产品的质量至关重要,而软件测试则是达成这一目标的关键步骤。本文将探讨软件测试的多维度作用,包括其在不同开发阶段的应用、面临的挑战以及未来趋势。通过分析自动化测试工具的选择、测试用例设计的最佳实践和持续集成的重要性,文章为读者提供了一套全面的质量保证策略,旨在帮助团队提升测试效率并优化产品质量。
|
5月前
|
SQL 运维 监控
老系统重构系列--稳定性摸排灵魂三问
该文主要讨论了老系统改造的过程和方法,特别是针对版权资产管理-财资系统的重构。作者强调了系统稳定性的重要性,并分享了他们团队在重构过程中采取的策略。他们通过确定目标、制定方法论和实施步骤来确保问题的全面摸排,包括核心链路图、流程时序图和问题路由图的绘制,以识别可能的问题和需要加强监控的部分。此外,文章还提到了数据对账监控和系统级统一监控的重要性,以及技术改造和预案的制定。作者提供了相关文章链接以供进一步阅读,并分享了他们在摸排和整改过程中的实际成果。
100 0