阅读更多

1顶
0踩

移动开发
在iOS项目开发中,当实现新功能时如果忽略可维护性而引入技术债务,将会需要延迟解决它或导致增加维护成本。开发者需要设置什么才能自动监控代码质量?通过适当运用Gcovr等一系列工具,就能有效提高代码质量。

当实现新功能时,如果忽略可维护性而引入技术债务,那将会需要延迟解决它或导致增加维护成本。

最近我们已经思考通过哪些方式来提高代码的质量:
  • 当代码的质量下降时,通过设置一些工具来马上提醒开发者;
  • 文档化一些编码规范和思考在过去的几个项目中如何避免维护性差的问题。


我将会简单地概括我们需要设置什么才能自动监控代码质量。
基础

我们选择一个持续集成工具Jenkins,让它运行在一台放在我们工作室的Mac Mini。其实我不怎么喜欢Jenkins,但到目前为止,它是最稳定和最适合的工具来完成这些工作。

我们已经通过Homebrewrbenv来分别安装Jenkins和Ruby,而rbenv能够为我们提供一个最新和稳定的Ruby Gems环境。有个Homebrew和Ruby Gems两个包管理工具之后,我们就几乎能够安装所有我们需要的工具,但很少会破坏与原有OS X系统更新提供的Ruby。

单元测试

我们使用Specta和Expecta来测试我们的iOS项目。

Specta让我们采用行为驱动开发(BDD)风格的语法来编写测试,相比于XCTest的语法,它更加易读。它还有一个强大的分组测试功能,在测试之前或之后运行一些代码块,这样的话,能够极大地减少重复代码。

Expecta是一个匹配器框架,我们可以在测试中使用它来创建断言。它的语法非常强大,与此同时,它比内建的XCAssert套件更加易读。例如:
expect(@"foo").to.equal(@"foo");
expect(foo).notTo.equal(1);
expect([bar isBar]).to.equal(YES);
expect(baz).to.equal(3.14159);

我们在开发时,通过XCode来运行测试;而使用通过Homebrew来安装的Jenkins时,会借助XCTool。XCTool是一个可代替的选择来xcodebuild,它能让你通过命令行的方式来非常轻松地运行测试套件和生成JUnit风格的测试报告。
$ xctool -workspace Project.xcworkspace -scheme Project -reporter junit:junit-report.xml test

这些测试报告会发布在Jenkins上,而Jenkins会使用JUnit Plugin来根据时间的推移提供单元测试结果的图表,同时会向我们显示我们的测试是否稳定。



Unit Test

Pull Request测试

我们想我们的测试尽可能运行以至于如果我们破坏什么东西,我们就会马上知道。我们在feature branches做些修改,然后提交一个pull request到Github,那么代码就会被另一个开发者审查。只要被打开,我们就能运行所有的测试来确保没有任何东西被破坏。

当新的pull requst是开放状态时,为了管理这些,我们安装Github Pull Request plugin来将信息从Github发送到Jenkins。如果有任何测试失败,它将会显示在Github,然后我们就不将代码合并,直到代码被修复为止。

代码覆盖率

我们也会用Gcovr工具来生成代码覆盖率报告,Gcovr的安装方式也是Homebrew。你需要针对main target的debug congfiguration改变两个构建设置来配置项目。将Generate Test Coverage Files和Instrument Program Flow都设置为YES。


Code Coverage


当我们运行单元测试来生成代码覆盖率报告时,我们需要将OBJROOT=./build添加到XCTool命令行的尾部。
$ gcovr -r . — object-directory build/Project.build/Debug-iphonesimulator/Project.build/Objects-normal/x86_64 — exclude ‘.*Tests.*’ — xml > coverage.xml

Gcovr输出的代码覆盖率报告也会被插件Cobertura Jenkins plugin发布,这个插件会提供一种可视化的方式来根据时间的推移来显示代码覆盖率。

现在我们不仅可以看到测试是否通过,还可以看到代码的测试覆盖范围。

静态分析

在工具集中,其中一个强大并能够保持高质量的代码的工具就是静态分析工具。这些工具会扫描你的代码,然后生成一个报告,这个报告会告诉你破坏代码风格规则的代码位置。举几个规则的例子:
  • 未使用的变量或参数
  • 长变量名,方法名或代码行
  • 覆盖一个方法,但没有在这个方法调用super
  • 方法太长或方法过于复杂
  • 还更多的规格...

我们使用OCLint静态分析工具,这个工具能够支持C,C++和Objective-C语言。OCLint通过结合XCTool使用来生成json-compilation-database reporter,从而提供great integration特性。我们首先添加另一个reporter到我们的XCTool命令行,然后将那个report传递到OCLint来执行静态分析。
$ xctool -workspace Project.xcworkspace -scheme Project -reporter junit:junit-report.xml -reporter json-compilation-database:compile_commands.json test
$ oclint-json-compilation-database -e Pods -report-type pmd -o oclint-pmd.xml

这个report以PMD的方式来生成,然后使用PMD Plugin被发布到Jenkins。有了这些插件之后,你也可以在测试失败之前,设置每个警告的优先级(底,中,高)中一些限制。最初,我们设置这些限制为低,那么只要我们引入代码,就会被提醒,从而提高代码质量。



自动部署

最后一个问题不是如何提高代码质量,而是如何节省时间。开发者通常都会将编译好的代码通过Crashlytics发送到设计师来设计审查,或在sprint结束演示时发给用户。发送一个已经编译好的App通常花一个开发者的10分钟左右时间,但它需要他们来切换任务和干扰他们的心流。

最近我们已经配置一个在夜晚构建系统,它会在早上自动发送一个新版本的App给每个人。

为了做到这样,我们使用fastlane。fastlane是一个定义lanes的一些操作来执行的强大工具集。现在我们有三个已经定义好的lanes,一个是用来发布给ribot开发者,一个是用来发布给在ribot的每个人,最后一个是发布给用户。
before_all do |lane|
 cert
 sigh
end
desc “Deploy a new build to ribot iOS developers over crashlytics”
lane :dev do
 ipa
 crashlytics({ groups: ‘ribot-developers’ })
end
desc “Deploy a new build to people at ribot over crashlytics”
lane :internal do
 ensure_git_status_clean
 append_build_time
 ipa
 crashlytics({ groups: ‘ribot’ })
 reset_git_repo
end
desc “Deploy a new build to everyone over crashlytics”
lane :external do
 ensure_git_status_clean
 increment_build_number
 ipa
 crashlytics({ groups: [‘ribot’, ‘client’] })
 commit_version_bump
 add_git_tag
 push_to_git_remote
end
after_all do |lane|
 clean_build_artifacts
end

通过使用fastlane工具(通过Ruby Gems来安装)来运行一个lane。
fastlane internal

在开始使用所有的lanes之前,我们应该自动确保我们有一个有效的signing certificate和最新的provisioning profile。所有我们的配置都放在一个.env文件,它让我们有些默认配置,但当我们运行fastlane根据需要来覆盖它们。

在将来,我们会通过使用deliver操作来自动化App Store提交过程。

最后总结

到目前为止,我们已经尝试这些过程,并在工程中呈现出好的结果。我们期望看到只要适当地使用这些工具,就能提高代码的质量,这些报告将会让我们随着时间推移来量化代码质量。我们期待在下一个工程中适当地使用这些工具会发生什么。

文章来源:Medium 作者:Matt Oakes

译者简介:刘耀柱(@Sam_Lau_13),iOS Developer兼业余Designer,参与开发技术前线iOS项目翻译,个人博客:http://www.jianshu.com/users/256fb15baf75/latest_articles。
  • 大小: 7.6 KB
  • 大小: 14 KB
  • 大小: 8.4 KB
1
0
评论 共 1 条 请登录后发表评论
1 楼 kanme818 2015-05-28 16:10
收藏,这个有用

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • 【java基础】——java虚拟机HotSpot

    一、前言 在自己电脑上输入java -version时出来:Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode),不知道是啥意思。查阅资料发现HotSpot是java的虚拟机。把前因后果写在下边。 二.、HotSpot历史 SUN的JDK版本从1.3.1开始运用HotSpot虚拟机, 20...

  • 一份深入解析Java虚拟机HotSpot手册,让我卷成美团架构师

    作为本书的开篇,本章将围绕Java的生态系统,简单介绍JDK、JVM、JEP,引导读者走进虚拟机的世界。1.1节介绍了各具特色的JDK分支和OpenJDK的子项目。1.2节介绍了Java改进提案,它们代表类Java社区最新的工作动向。1.3节简单描述了历史长河中存在或者曾经存在的Java虚拟机。1.4节讨论了HotSpotVM的组件、源码结构、构建、调试以及修改代码后如何回归测试。最后1.5节展望未来,讨论了Java的前沿技术Graal VM。

  • 【Java虚拟机学习——对象相关学习】HotSpot虚拟机下对象的生命周期、对象的创建及在Java堆中对象的内存分配、布局和对象的访问

    HotSpot虚拟机下对象的创建及在Java堆中对象的内存分配、布局和对象的访问

  • JVM学习笔记002:垃圾回收

    三、垃圾回收 1、如何判断对象可以回收 引用计数法 一个对象被引用+1,一个对象不再引用-1,为0时可以回收 弊端:循环引用时,两个对象的计数都为1,导致两个对象都无法被释放 可达性分析算法 根对象:肯定不能被回收的对象 JVM中的垃圾回收器通过可达性分析来探索所有存活的对象 扫描堆中的对象,看能否沿着GC Root对象为起点的引用链找到该对象,如果找不到,则表示可以回收 可以作为GC Root的对象 虚拟机栈(栈帧中的本地变量表)中引用的对象。 方法区中类静态属性引用的对象 方法区中常量引用的对象

  • Java 11 到 Java 17 的最佳 HotSpot JVM 选项和开关

    一、前言 在本文中,你将了解 OpenJDK HotSpot Java 虚拟机 (HotSpot JVM) 中的一些系统知识,以及如何调整它们以获得最佳状态适应你的程序和运行环境。HotSpot JVM 是一项了不起且灵活的技术。它作为二进制版本适用于每个主要操作系统和 CPU 架构,从微型 Raspberry Pi Zero 一直到包含数百个 CPU 内核和 TB 级 RAM 的“大型”服务器。由于 OpenJDK 是一个开源项目,HotSpot JVM 几乎可以针对任何其他系统进行编译,并且可以使用选项

  • HotSpot的算法细节实现

    本章设置这部分内容主要是 为了稍后介绍各款垃圾收集器时做前置知识铺垫。 1、根节点枚举 我们以可达性分析算法中从GC Roots集合找引用链这个操作作为介绍虚拟机高效实现的第一个例子。固定可作为GC Roots的节点主要在全局性的引用(例如常量或类静态属性)与执行上下文(例如 栈帧中的本地变量表)中,尽管目标明确,但查找过程要做到高效并非一件容易的事情,现在Java应用越做越庞大,光是方法区的大小就常有数百上千兆,里面的类、常量等更是恒河沙数,若要逐个检查以这里为起源的引用肯定得消耗不少时间。 迄今为止,所

  • java HotSpot

    1. HotSpot历史 SUN的JDK版本从1.3.1开始运用HotSpot虚拟机, 2006年底开源,主要使用C++实现,JNI接口部分用C实现。 HotSpot是较新的Java虚拟机,用来代替JIT(Just in Time),可以大大提高Java运行的性能。 Java原先是把源代码编译为字节码在虚拟机执行,这样执行速度较慢。而HotSpot将常用的部分代码编译为本地(原生,native)...

  • JVM:Java程序的核心引擎

    JVM的作用是将Java源代码转换成可执行的字节码,并在运行时负责执行这些字节码。当程序要运行时,JVM会将字节码文件加载到内存中,并将其转换为机器码,然后执行它们。3.自动内存管理:JVM有垃圾回收机制,可以自动回收不再使用的内存,减少程序员的内存管理负担。1.跨平台性:由于JVM可以在不同的操作系统上运行,所以Java程序可以在多个平台上运行。4.高性能:JVM的执行引擎可以将字节码转换为机器码,提高程序的执行效率。2.资源占用:JVM需要占用一定的内存和CPU资源,可能会影响系统的性能。

  • 【架构】Java实现游戏引擎

    学过编程后,感觉所有的游戏都离不开两个方法,一个是画面更新,一个是指令输入。既然大多数的游戏都离不开这几步,那么为了便利游戏的开发,一些工程师就把这几个方法抽象出来,定义为一个规范,游戏开发者只需要根据这个规范实现游戏的业务逻辑就可以简单高效的开发出一个游戏。这个规范就是所谓的。这篇文章就用JAVA语言来实现一个简易的游戏引擎。

  • (深入理解 Java 虚拟机)一篇带你探索 HotSpot虚拟机在Java堆中对象分配、布局和访问的全过程

    文章目录一、对象的创建二、对象的内存布局三、对象的访问定位 一、对象的创建 Java是一门面向对象的编程语言,Java程序运行过程中无时无刻都有对象被创建出来。在语言层面上,创建对象通常(例外:复制、反序列化)仅仅是一个new关键字而已,而在虚拟机中,对象(文中讨论的对象限于普通Java对象,不包括数组和Class对象等)的创建又是怎样一个过程呢? 当Java虚拟机遇到一条字节码new指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载、解析和初

  • JVM技术细节: HotSpot的内存模型

    1、对象无句柄 在早期的JVM版本,例如 Classic VM 实现中,使用了 间接句柄(indirect handle) 来表示对象引用。 虽然使用这种方式使得垃圾收集器在重定位对象(relocating)时非常方便,但却导致了严重的性能瓶颈,因为每次访问Java对象的实例变量都需要两步操作。 HotSpot 推出以后,Java 代码就不再使用任何句柄。 对象引用使用 直接指针(direct p...

  • Java8新特性总结 -8.Nashorn , JavaScript引擎

    所有示例代码打包下载 : 点击打开链接Java8新特性 : 接口新增默认方法和静态方法Optional类Lambda表达式方法引用Stream API - 函数式操作流元素集合Date/Time API新API和工具Nashorn , JavaScript引擎8 . Nashorn , JavaScript引擎    从JDK 1.8开始,Nashorn取代Rhino(JDK 1.6, JDK1....

  • 代码三部曲,最全代码治理知识体系(上)

    1.问题1、代码管理是什么,包含哪些内容?2、如何建设合适的代码仓库,如何规范治理代码仓库?3、如何应用版本控制工具,选择合适的分支策略,适应不同的开发模式?4、项目开源需要注意哪些环节...

  • Apache Lucene 8.0.0 发布,Java 全文搜索引擎

    开发四年只会写业务代码,分布式高并发都不会还做程序员? >>> Lucene PMC 宣布推出 Ap...

  • 快速了解什么是HotSpot

    待更。。。

  • 什么是HotSpot?

    没错,Java是解释语言,但并不意味着它一定被解释执行。早期 的虚拟机确实一条一条指令解释执行,但人们发现这样效率太低, 不满足各种要求,因此出现了许多其它虚拟机,如JIT的虚拟机。 HotSpot也是类似一种虚拟机,自从SUN买下后,已经把它放入 JRE 1.3以及后续版本中。  采用HotSpot的Java虚拟机,已经很难说Java是被虚拟机解释执行了, 原因是HotSpot实际上是把Java

  • 八、JVM(HotSpot)虚拟机字节码执行引擎

    注:本博文主要是基于JDK1.7会适当加入1.8内容。 物理机执行引擎:直接建立在处理器、硬件、指令集和操作系统层面。 虚拟机执行引擎:由虚拟机自定义实现,自行制定指令集与引擎体系结构,能够执行不被硬件执行的指令集合。(符号引用—-直接引用) 1、运行时栈帧结构 定义:用于支持虚拟机进行方法调用和方法执行的数据结构,虚拟机运行时数据区中的虚拟机栈的栈元素。存储了局部变量表、操作数栈、动态链...

  • 学JAVA不会搜索引擎,小白也能看懂的引擎基础知识

    学JAVA不会搜索引擎?小白也能看懂的引擎基础知识 xl_echo编辑整理,欢迎转载,转载请声明文章来源。更多案例、资料请联系QQ:1280023003 在java开发中所说的搜索引擎可不是平常我们接触的“百度”,“google”,“搜狗”,它是一项java开发的基于Lucene的搜索服务器。目前java开发使用的最多的两款引擎技术一个是:Elasticsearch,另外一个就是:Sola...

Global site tag (gtag.js) - Google Analytics