Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

《持续集成》—— Paul M.Duvall / Steve Matyas / Andrew Glover #32

Open
thzt opened this issue Jun 25, 2018 · 0 comments
Open

《持续集成》—— Paul M.Duvall / Steve Matyas / Andrew Glover #32

thzt opened this issue Jun 25, 2018 · 0 comments

Comments

@thzt
Copy link
Owner

thzt commented Jun 25, 2018

如果您遇到很痛苦的事情,似乎一个比较好的建议就是更频繁的去做这件事。

关于持续集成,一件有趣的事情就是人们常常对它产生的影响感到吃惊。
我们经常发现人们认为它的好处不大,但它却给项目带来了完全不同的感觉。
项目的可见性变得好了很多,因为问题能够更快的检测出来。

因为引入缺陷和发现缺陷之间的时间变短了,缺陷的发现就更容易,您可以很容易的看看改变了什么,以便帮助您找到问题的根源。
与良好的测试程序配合时,可以大大减少缺陷的数量。
结果是,开发者在调试上花的时间减少了,在增加功能上花的时间更多了,他们相信自己是在一个坚实的基础上开发软件。


对我来说,它代表了我成为一名高效率软件开发者的主要目标之一:
将重复的,容易出错的过程自动化。

一个人开发的项目中,依赖外部系统又比较少的话,软件集成不会成为太大的问题,但是随着项目复杂度的增加(即使只增加一个人),
就会对集成和确保软件组件能够一起工作提出更多的要求——要早集成,常集成。
等到项目快结束时才来集成会导致各种各样的软件品质问题,解决这些问题代价很大,常常会导致项目延期。

CI(continuous integration)以较小增量的方式迅速的解决这些风险。

开发团队不应该相信因为CI系统自动化了,就可以避免集成问题。

持续集成增加了您获得反馈信息的机会。这样,您每天都能多次了解项目的状态。
CI可以用来减少引入缺陷和修复缺陷的时间,从而改进总体软件品质。

“持续”这个术语从技术上来说是不对的。“持续”意味着某事一旦启动就不会停止。
这意味着集成过程一直在执行,但是即使对于最密集的CI环境来说,也不是这样的。
所以,“持续集成”的含义更像是“经常集成”。


“每天吃一个苹果”和实际这么去做是两码事。

一次构建不止是一次编译。
一次构建可能包含编译,测试,审查和部署以及其他一些事情。
一次构建的将源代码放在一起,并验证软件可以作为一个一致的单元运行的过程。

CI场景中的步骤通常是这样的:
(1)一名开发者向版本控制库提交代码。同时,集成构建计算机上的CI服务器正在轮询检查版本控制库中的变更。
(2)在提交发生之后,CI服务器检测到版本控制库中发生了变更,所以CI服务器会从库中取得最新的代码副本,执行构建脚本,该脚本将对软件进行集成。
(3)CI服务器向指定项目成员发出电子邮件,提供构建结果的反馈信息。
(4)CI服务器继续轮询版本控制库中的变更。

CI需要具备的特征:
(1)与版本控制系统连接
(2)构建脚本
(3)某种类型的反馈机制
(4)集成源代码变更的过程

CI的一个关键目标就是要提供集成构建的反馈信息。
因为您需要尽快知道最近一次构建是否存在问题。
如果立即得知这些信息,您就可以很快的修复问题。

很多人认为,没有自动化的,持续的测试的CI不能算作是CI。
我非常同意。
没有自动化的测试,开发者或其他项目风险承担者对软件的变更很难有信心。

一个好的CI系统的关键特征就是“速度”,CI系统的本质是及时向开发者和项目风险承担者提供反馈信息。


假定是所有麻烦之母。

软件开发中最重要的问题之一就是假定。
如果您假定一个方法将得到正确的调用参数,那么这个方法就会失败。
如果假定开发者都会坚持编码标准和设计标准,那么软件就会变得很难维护。
如果假定配置文件没有改变,那么您就会花上不少宝贵的开发时间来追踪不存在的问题。
如果在软件开发时对某些问题想当然,我们就会浪费时间,增加风险。

持续集成在每次版本控制系统发生变更时就执行构建,这有助于减少项目中的假定。

开发软件需要对变更做好计划,持续的观察结果,并根据结果增量的修正路线。
这正是CI的工作方式。

CI包含了一组策略,让软件开发者能够对代码进行修改,知道如果我们对软件造成了破坏,就会马上收到反馈信息。
这种即时的反馈让我们有时间修正路线,根据变化迅速的调整。

检查软件的品质,就是检查最新的集成构建,就这么简单。

CI的价值是什么:
(1)减少风险
(2)减少重复过程
(3)在任何时间,任何地点生成可部署的软件
(4)增强项目的可见性
(5)对开发团队的软件产品建立起更强大的产品信心

最好在项目早期就实现CI。
如果你在项目晚期开始实现CI,要从较少的工作开始,在时间允许的情况下加入更多的东西。

CI不仅是一种技术上的实现,它也是一种组织上和文化上的实现。
人们常常拒绝改变,在组织中引入改变的最佳方式可能是一点一点的在过程中增加这些自动化的机制。

在项目中实现CI的团队有好处的7项实践:
(1)经常提交代码
(2)不要提交无法构建的代码
(3)立即修复无法集成的构建
(4)编写自动化的开发者测试
(5)必须通过所有测试和审查
(6)执行私有构建
(7)避免签出无法构建的代码


大部分开发团队在一开始都怀有良好的意愿,但有一些团队还是被项目中遇到的问题压垮了。
产生这些问题就是因为没有管理风险。

我们很少听到开发团队会说“我们认为测试和代码复查是不好的实践”,
但是,当受到进度压力的影响时,这些实践通常会被开发团队率先放弃。

如果您可以减少某些软件开发风险,您就能够改进软件品质。
在任何项目中,都有许多风险需要管理。
我们关注那些可以利用CI来减少的关键风险。
(1)没有可部署的软件
(2)很晚才发现缺陷
(3)缺少项目的可见性
(4)低品质的软件

您可能意识到了某些风险,却没有对它进行必要的缓解。


软件开发过程中耗时的任务同样也可以通过自动化构建实现机械化。
如果工人的工作在他的8小时工作日中都忙于一些手工任务,那肯定就没有时间来监控过程和产品,计划改进以及其他工作。

有时候开发者就像是鞋匠,为他的所有客户都提供了鞋子,却忘记了为他自己的孩子做鞋。
我们为用户创建了应用程序使过程自动化,但我们没有自动化自己的软件开发过程。

把所有需要的东西都放到源代码版本控制库中,以便于您通过单个命令就能构建整个系统。

为了能够有效的构建软件,所有软件资产都必须集中放置。
在使用版本控制库集中存放“所有”软件资产时,您仍然需要判断“所有”都包含了哪些东西。
要利用项目的级别或风险来确定放在版本控制库中的软件资产至少应该包含哪些东西。

为了能够在项目开发过程中从版本控制库中取出所有各种可供使用的资产组合,您必须创建一致的,有逻辑的目录结构。

让构建快速失败。
好的构建知道如何快速的失败。
在构建的许多部分都成功之后再失败,这让人很恼火,而且您在确定失败的目标时也会失去宝贵的时间。

对于一个具体的项目,这取决于什么最有可能经常会失败。
它越有可能失败,您就应该越早的在构建脚本中执行它。


持续数据库集成(CDBI)是一个过程,即每次项目的版本控制库中发生变更时,重建数据库和测试数据。

数据库集成是集成按钮的一部分,因为它基于一个原则,
即数据库代码在本质上与系统的其他源代码没有差别。

通过对数据库集成自动化,您还能获得一项重要的能力,
即团队中的每个人都能在他们自己的工作站上创建一个本地数据库实例。
每个团队成员因此可以创建一个数据库“沙盒”,使得对数据库进行变更和测试不会影响到他人。

实现自动化,共享和构建数据库集成过程的目的就是要让这些过程持续进行。

让每个开发者能够修改数据库。
每个开发者都应该能够修改任何一部分数据库脚本。
这并不是意味着每个开发者都会去修改这些数据库脚本,因为并非每个开发者都有必要的数据库专业知识。

因为每个开发者都有自己的数据库沙盒,所以每个人都能修改本地的数据库然后将变更提交到版本控制库。
这将减少DBA的瓶颈,使开发者能够进行必要的变更。

不论什么使得构建失败,首要的工作就是修复它。
回报随之而来,所做的修复得到集成,这个问题不会再次发生。

打破障碍,让数据库小组成为开发团队的一部分。


可靠性——在连续的试验中给出同样的结果。

系统工程有一项原则,线性系统的可靠性是每个系统组件的可靠性的乘积。

为了获得高可靠性,大桥的建造者和钢笔的制造者,必须从最低层开始确保组件的可靠性,
因为这才是确保整体可靠性的唯一方式。

大部分软件系统如果没有几千个对象,也有几百个对象,
对于包含100个组件的线性系统来说,如果每个组件的可靠性是99%,整个系统的可靠性就只有37%。

如果您想构建一个软件系统,它在服务层面的承诺达到100%,您绝对需要在单个对象的层面上确保可靠性。
如果您不能从最低层确保并测量可靠性,您就不可能在系统层面上达到要求。
然而,这正是我们整个行业一直以来构建和交付软件的主要方式。
设计,构建,然后抛给质量保证(QA)小组。QA小组在系统层面上进行测试,然后不可避免的发现许多缺陷。

所以作为底线,如果我们要构建真正可靠的软件系统,我们就必须确保对象层面的可靠性,这只能通过成功的单元测试来实现。
否则,我们就不能期望构建出高可靠的应用程序。
当然,只是为对象编写单元测试不一定能保证可靠性。测试必须有效的使用了被测对象,而且必须经常执行。

因为软件系统中的对象相互之间进行通信,每次当系统发生变更时,测试都必须执行。
在CI系统中包含持续的测试让您能够做到这一点。

开发者测试和CI可以减少软件缺陷发生的频率,但说实话,缺陷仍会发生。
为缺陷编写测试,保证缺陷一旦被发现,就再也不会出现。


代码复查是由人来执行的,而人是讲感情的。
这意味着人们可能不会告诉其他同事他们的代码写的很臭,在一个工作环境下工作的同事可能会在复查别人的工作时不客观。
代码复查比较费时,即使是在沟通很好的环境之中也是如此。

基于人的审查与静态分析工具执行的审查之间的区别有两点:
(1)这些工具经常运行的成本很低
(2)这些工具具有计算机的无所畏惧和无情的客观性

利用工具进行自动化的代码审查能解决的80%的问题,让人来处理另外20%的重要问题。

传入耦合(Afferent Coupling)和传出耦合(Efferent Coupling)都反映了一个架构维护问题:
要么这个对象对其他太多对象负有责任(高传入耦合),要么这个对象不够独立于其他对象(高传出耦合)。

传入耦合高的对象会造成破坏,传出耦合高的配件则会受到破坏。
同样,为这些配件编写足够的测试,达到一定的代码覆盖率,将会有助于开发团队快速定位问题。

不稳定性 = 传出耦合 / (传出耦合 + 传入耦合)
值为1表示不稳定,值为0表示稳定。

持续评估代码品质。


如果组织机构付钱让您写软件,那么付钱的组织机构很可能希望您在一段时间之后向最终用户提供能工作的软件,这段时间是可预测的,也是符合实际情况的。
因此,我们有理由认为我们这个行业应该已经找到了一种可靠的方法,在期望的时间表内向最终用户提交高品质的,能工作的软件。
但是我们仍然会听到“噩梦发行版”的故事,它们失去控制,每个人有过惊慌失措,失眠,长出更多白头发——而且仍然可能没有办法向最终用户提供新的发行版。

高效的创建能工作的软件是专业软件开发者存在的理由。
没有成功的开发,软件就不可能存在。

如果您不能发布您的软件,那么其他事情就几乎相当于不存在。


软件项目中的信息一直在变化。
我们必须与客户,开放者,管理层或项目的其他风险承担者沟通信息,沟通恰当,准确和及时是特别重要的。

在正确的时间,以正确的方式,将正确的信息发送给正确的人——CI是让这种反馈信息自动化,目标化和实时化(持续化)的最好工具。

向项目中的每一个人发送信息通常只会导致每个人都忽略该信息。

持续集成的核心是减少缺陷引入,发现和修复之间的时间间隔。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant