[TOC]
> 交付管道的建立和自动化是持续交付的基础
## 持续集成
更关注代码质量。持续集成是为了确保随着需求变化而变化的代码,在实现功能的同时,质量不受影响。因此,在每一次构建后会运行单元测试,保证代码级的质量。单元测试会针对每一个特定的输入去判断和观察输出的结果,而单元测试的粒度则用来平衡持续集成的质量和速度。
持续集成的核心价值在于[1](http://growth.phodal.com/#fn1):
1. 持续集成中的任何一个环节都是自动完成的,无需太多的人工干预,有利于减少重复过程以节省时间、费用和工作量;
2. 持续集成保障了每个时间点上团队成员提交的代码是能成功集成的。换言之,任何时间点都能第一时间发现软件的集成问题,使任意时间发布可部署的软件成为了可能;
3. 持续集成还能利于软件本身的发展趋势,这点在需求不明确或是频繁性变更的情景中尤其重要,持续集成的质量能帮助团队进行有效决策,同时建立团队对开发产品的信心。
### 持续集成系统
在前面的内容里,我们已经介绍了持续集成的各项基础设施——如使用版本管理、编写测试、自动化部署。要构建这样的一个持续集成系统需要下面的内容:
* 支持自动构建
* 源码服务器
* 持续集成服务器
我们已经实现了前两点,针对于第三点——持续集成服务器,我们可以以 Jenkins 为例做一些简单的说明。它是一种基于 Java 开发的持续集成工具,并提供了用于监控持续重复工作的软件平台。
它可以让整个开发流程到部署都实现自动化。由于每个功能可以一点点的加在 build 中,那么这样就能保证每次的新 build 可以交付新的功能。同时,我们可以根据用户的反馈情况及时调整开发方向,降低项目风险。
### 持续集成流程
我们就可以对这个工作流展开进入介绍。持续集成重要就是要保证整个过程是**可持续**的。如下图是一个持续集成的工作流:
![](https://box.kancloud.cn/2016-05-16_57398db6971dd.jpg)
CI Workflow
不同的开发者在自己的机器上开发功能代码。在完成一定的本地提交后,这些代码将会提交给源代码控制服务器。不过,在那之前我们应该在本地跑测试来减少持续集成失败的情况。接着,我们的CI会定时去获取源码服务器是否有代码修改。如果有代码修改,那么我们的集成服务器将会获取这些代码。然后,构建这个项目,运行测试,再输出返回结果。最后,我们可以开发一些小工具来提醒用户 CI 是否运行成功。
如果这个过程中,我们我们的 CI 运行失败的话,那么我们就不能再提交新的代码——除了修复 CI 的代码外。持续集成变红不能过夜,要么快速解决,要么回退。
在这个过程中,有两点值得注意,一个是小步前进,一个是迟早反馈。
#### 小步前进
小步前进是一系列步骤的集合,其目的是:集成越早问题越小。即当我们的代码越早的提交到源码服务器,那么其他人就可以尽可能早的和我们的代码集成到一起。这也意味着,每天结束时,我们在本地的修改要尽可能小,并且这些修改还要保证不会破坏持续集成。
我们需要频繁地在本地提交我们的代码,编写独立的测试——如果我们在最后才编写测试,这会拖慢整个流程,它使得我们不能尽可能早的提交代码。
#### 尽早反馈
> 反馈越早,那么问题越小。
无论是精益还是敏捷都在强调一点——尽早反馈,反馈对于提高敏捷开发流程效力非常重要。从日常的:
* Code Review
* 静态代码分析
* 自动集成测试
* 自动验收测试
* 高频率发布
我们都在做尽可能小的反馈,这些实践对于我们完成一个好的持续集成来说是非常重要的基础。
参考资料:
-《持续交付:发布可靠软件的系统方法》
## 持续交付
持续交付依赖于一系列的工具和实践,下图是一个持续交付的工作流:
![](https://box.kancloud.cn/2016-05-16_57398db6b2a6d.jpg)
CD Workflow
还有一系列与开发无关的技能:
1. 自动化
2. DevOps
3. 云基础设施
4. 以软件为中心的哲学
### 基础设施
在我们使我们的项目可以持续交付软件包的时候,我们需要
#### 本地开发环境
在本地编写代码时,我们需要设置本地的开发环境。假设我们要开始一个 Java Web 项目,在我们的开发机器上,我们需要安装:
* 版本管理工具,如 git,用于管理源代码。
* IDE,如Intellij IDEA,用于搭建开发环境。
* 构建工具,如 gradle,用于安装依赖、运行测试、构建工程等等。
* 语法检测工具,如 checkstyle,用于检查代码语法。
* 单元测试框架,如 JUnit,用于进行单元测试。
* 集成测试框架,如 Cucumber、Selenium,用于做行为测试。
除此,在我们的项目代码里,我们还需要:
* `CI运行脚本`,用于在 CI 上运行指定的测试。
* `上传包脚本`,用于上传 build 完的软件包。
* `部署脚本`,用于在本地部署包到测试环境。
* `监控代码`,用于监测网站性能和用户行为。
当然我们还需要辅助一些测试工具来测试网站,如性能测试、网络测试等等。
#### 持续集成环境
为什么在这里会出现一个持续集成环境?我也不知道,只是想到了这里。由于我们需要持续集成,所以我们也需要一个运行持续集成服务器的机器。
持续集成服务器是由两部分组成的:Master 和 Agent。即一个用于控制其他运行持续集成服务的机器,以及执行指令的机器。因此,我们需要在一台机器上安装 Master 软件,在另外一台机器上作为 Agent。在我们的 Agent上,我们需要安装相对应的运行服务的软件,如
* 指定版本的语言环境 ,如Java、Python。
* 构建工具。
* 版本管理工具,及对应的密钥。
* 打包工具,如 RPM。
* 虚拟桌面,即可以模拟桌面浏览器的软件。
同时,我们还需要有一个地方放置我们的RPM包。
#### 测试环境
相比于上面两个环境来说,测试环境就比较简单了。我们只需要创建几个不同的环境,即开发者的测试环境、QA 环境、模拟线上环境,在这几个不同的环境上有不同的配置。
### 持续部署
在持续交付之外的,还有持续部署——这个就更依赖于团队的组织结构了。其与持续交付的对比如下图所示:
![](https://box.kancloud.cn/2016-05-16_57398db6d6e87.jpg)
持续部署
我们可以从图中看到,两者的最大不同之处在于:持续部署会直接将构建生成的部署到产品环境。这就意味着,我们不仅要有强大的技术实力,也要有足够的组织支持才能做到。而这部分已经超出了软件开发的内容了~~。
## 持续学习
如果说`持续交付则是一种对卓越的追求`,那么`持续学习应该就是追求软件卓越`。 如果说`持续集成是一种软件开发实践`,那么对于技术人员来说——`持续写作应该就是持续学习的实践`
生活总会遇到压力,来自工作上的也好,来自对于技术上的兴趣也罢,我们需要持续来断地学习。没有一直能立于不败的方法,在传说中的武林上也是如此。
对于持续学习来说,通常会有以下的
* 阅读
* 编程
* 写作
有意思的是持续学习有额外的好处便是
* 持续学习可以降低危机感
### 持续阅读
看过如此多的金庸、古龙小说我们都会发现有那么多的人都在追求武功上的卓越,有的走火入魔了,有的铤而走险杀人放火,暂且不讨论这些。我们简单的以大部分的主角为例,大部分的主角自小就练得一手好武艺,少部分除外,而他们通过会比前辈厉害,只是因为我们看了前人的说,现在也是如此。
**20 年前要建一个淘宝怕是没有两三个月十几个是不行的,但是今天要建出原来淘宝的模样,也许一个人单枪匹马一两天就能搞定了,还能上线。**
有意思的是武林小说的武林秘籍少之又少,正常情况下能学到的或许就是教科书上的种种。而现在,如果我们要学习 `UX` 的话,我们很容易可以从亚马逊上拿到一个书单,又或者是某个博客里面列举出来的:《用户体验要素》、《交互设计沉思录》、《怦然心动——情感化交互设计指南》等等。
我们可以更加方便快捷地获取我们所需要的知识从书上、网上等等。
`阅读更多的书籍是持续学习的基础。`
总会听到有些人在工作之余看了更多的书,在某种情况下来说是有意义的。我们需要不断地去阅读。
### 持续编程
编程算是一个开发人员工作时一直在做的,而对于工作之后来说,到底还会有多少人继续编程就是一个有意思的问题。
对于一个有兴趣的程序员来说,工作和兴趣都是分开的,可以将工作视之为无味的东西,但是休息时间呢?可以用来创造自己觉得有意义的东西,可以用来认识更多志同道合的人,对于不满现状的人更是如此,或许为自己创造了更多的机会。
如果工作之后编程,不应该是为了工作而编程,应该为了兴趣而编程,或者其他。如果没有时间,是不是因为加班了,对于刚开始养家糊口来说加班是没有办法的,但是如果不是的话,又没时间,是不是……
### 持续写作
对于一个技能人员来说,写作可能不是一件有意思的事,但是也不是一件很难的事,没有必要将大量的文字用文本表示。写给其他技术人员看的,有时候更多的是代码、思路、图。写作对于学习的意思怕是有一大把,写作是最好的输入,也是最好的输出。你需要为你的这篇文章
* 去参考更多的资料
* 更深入的学习
* 更多的时间付出
然而这些都是有价值的,你也许可以从中得到
* 一份工作
* 一些志同道合的朋友
* 一个博客
* 一种习惯
* 还有人生
* 或许还能写书。
对于我来说,更多的是对于`读者`和 `SEO` 的兴趣,SEO 是一门艺术。