Day 28 「最好避免犯错的方法」单元测试与 GitFlow、主线开发

廿一世纪的软件开发有一句名言:「最好避免犯错的方法,就是『天天犯错』」。

以前我们很喜欢「规格」,认为不管什麽事,只要你规格开好来,我就能照规格刻给你。长久下来,你最常听到 RD 挂在口中的话就是:

  1. 请 PO 去确认需求
  2. 这个当初需求没讲

这不是 RD 的错,这是一种文化的养成,这种文化是综合所有 Force 後的 Context ,所塑造出来的 Form。


图片来源:https://www.slideshare.net/teddysoft/pattern-based-problem-solvingpublished

客户有一个待解问题,为了解决问题,大家不断尝试、不断改善,终於找到一个能解决问题的 Solution,就把它写下来留给後人,经过一段时间的验证都没有问题,就写成规定裱起来,挂在办公室大门口,形成了我们的「SOP」,也就是 RD 在这个 Form 下,自然而然演化出来的 Solution。

在外力不会变的情况下,SOP 是方便有效的,但是,在廿一世纪的现代,外力是每天都在变的,昨天的假设今天会不存在,昨天以为的需求今天必需避免。

那怎麽办?

那就往回退一步,回到 Solution 还没被提出前,继续「不断尝试、不断改善」,找出新 Solution,然後,外力又改变,没关系,我们再继续「不断尝试、不断改善」…。外力不会停止改变,我们就是每天试错,每天改善,每天都比昨天更好、更快、更能适应环境。

这,不就是敏捷吗?

回到主题,今天要来聊两种版本管理的分支策略: GitFlow 与 主线开发。这两种策略都适合敏捷开发,但即便你不用敏捷开发,还是可以使用它们来管理你的程序版本。

GitFlow


GitFlow,图片截自网路

GitFlow 是一种「开出去再并回来」的分枝策略。如上图所示,GitFlow 的发明人 Vincent Driessen 根据开发过程中常见的场景,分出几种「常驻型」分支,与「临时型」分支,藉以帮助开发人员有条理地管理功能的开发、修复与释出。

develop

develop 是常驻型分支之一,它代表的是「开发完成、开发者认为没问题的功能」,於是,在 develop 上面的每一个点,都代表着一个相对稳定的功能,或一个已被修复的错误。在一个产品线上,develop 随时待命,等待成熟时机,就要合并入 master 而成为正式功能了。

feature

feature 是一种临时型分支,它「始於 develop,终於 develop」,当有开发任务时会从 develop 上长出来,结束後再回到 develop,一般而言,一个 feature branch 只负责一个功能,而且「越短命越好」,譬如说一两天以内。才能避免 merge 时的「conflict 地狱」。

master

如果说 develop 上的点是「相对稳定」,那 master 上的点就是「很有信心」的功能了。当 Release 时机成熟,我们会从 develop 合并进 master 来,并给一个版号,在 Git 上通常就是下一个 Tag。也就是说,GitFlow 规定你,在正式环境上的系统,一定要从 master 上拿,如非必要,不可以有例外。

release

release 也是一个「短命」的临时型分支,在需要 Release 时从 develop 分出来,有些人会在上面写一些 Release Note,有些人会拿去做预产线测试,有些人则单纯只是拿来当一个缓冲,求个心安…。但无论如何,没有人会养一个长寿的 release branch 的。如果这个分支真的遇到什麽无法短时间内解决的问题,一般就会建议直接放弃 Release,看看是什麽问题,再从 develop 开 feature 出来修。当然,如果是小问题,就直接在 release branch 上修一修,再同时 merge 回 develop 与 master 就好了。

hotfix

同属临时型分支,hotfix 跟 feature 有点像,但有两点不同。第一,它从 master 开出来,第二,它「只能修 bug,而且是紧急的 bug」。GitFlow 规定,决不能在 hotfix 上加新功能,否则会破坏 GitFlow「以 develop 为中心」的设计精神,这点非常容易忘记,会牢记。

哇!这麽复杂?

对的,GitFlow 的五大分支的组合的确是有点复杂,作者就是希望开发者学会了以後,往後开发上遇到的状况,都有对应的方法可以解,就不用老是随机应变、临场发挥了。

主线开发

有人喜欢严谨的管理风格,就有人喜欢简单自由。近年来流行的「主线开发」就属於这种。

所谓的主线开发,正如其名,开发者不用开 branch,大家都在 master 上面加功能。正因为大家都在主线上,所以相较於 GitFlow,流程简单很多,也没有什麽硬性规定,自由度很高。

没有 branch,那不同 RD 要怎麽同时开发多个功能?

其实这件事情,早在 Linus Torvalds 当年发明 Git 时,就已经想好了。Linus 认为,以前的版控工具,如 SVN,远端一定要有一个中央控管的 Server 在那边,又笨又丑。他认为,在一个团队中,人人都应该要可以是彼此的「远端 Server」,如此一来,我们可以今天 pull 你的 code,明天 push 到他的 repository,这样「去中心化」、「分散式」的设计,才够自由方便

举例,史提夫跟戴夫同时要开发两个功能,他们先从共用主机 origin 把 master 拉回自己电脑,开始开发。史提夫动作比较快,先做完测完并回主线,这时戴夫发现主线有变动,为了不确保自己的修改不会弄坏,於是先再拉一次 master 回来 merge,如果没事就没事,如果有问题,就在自己电脑上修复,修好测好再往上推,完成。

但是,如果两人开发差不多快,无法确定谁要先 push 时该怎麽办?这时,史提夫可以先到戴夫的 repository 去先把程序 pull 下来 merge,跑过测式,确认没问题,自己的功能也写完测完以後,再把两人的 code 一起 push 到 origin 去。

在 Git 发明之初,Linus Torvalds 本来就是想要建造一个「去中心化、分散式」的版本管理工具,因此使用 Git 时,每个人都可以是彼此的 remote,每个人都可以 pull 彼此的程序,而且不管你是什麽分支,大家讲好就好。

从这个角度看起来,其实「主线开发」更符合 Git 原始的精神,因为它根本就没有 branch,就大家都是 master,彼此自由地依需求 merge 来 merge 去。

万一开发完的功能还没要上怎麽办?

其实这件事不只主线开发会发生,GitFlow 也会,只是主线开发会使状况更明显而已。啊解决方法也不难,就是设一个 Feature Toggle,先把开关关闭,等有需要时再打开就好。

碍於篇幅,这里对 Feature Toggle 不多做细节的说明,读者可参考文末附上,Miles Chou 的部落格中,对 Feature Toggle 的说明与释疑。

共同点:瘦

不论如何你用哪一种方法,有一件事笔者建议你务必要遵守:「瘦」。不管是 GitFlow 的一个 branch,还是主线开发的一个 local repository,我们都会遇到「merge」的问题,而唯一能解决此问题的方法就是,每个功能都不要太大,要经常 merge,因为经常 merge,每次 merge 时要解决的问题才会比较小,而小问题肯定比大问题好解,不管是 conflict 还是 bug。

这也点出了一个重要的观念:「有 merge 就要跑全测试。」

每次的 merge,不管是 remote master 与 local master 的 merge,还是 feature branch 与 develop branch 的 merge,都是两种版本交会的地方,此时就比较可能遇到「原版本开发时没想到的问题」,因此,不论你平常多久跑一次测试,至少在 merge 的点上,你一定要跑一次全测试,才能确保正确性。

这时,单元测试的重要性就出来了。你知道 merge 的点容易出错,所以要测,但是你又没有单元测试,得靠人工验测,而人工验测又旷时费日,所以你就不敢天天 merge,然後久久 merge 一次就错误百出,然後就更不敢 merge…,多常见的恶性循环啊!

想打破这个恶性循环吗?那就来写单元测试吧,哪怕只有一个都好,就从明天开始。


Miss Ko,图片截自网路

谜之声:「打破他!」

Reference

  1. Git Flow :https://tinyurl.com/3cdjt7rc
  2. Feature Toggle:https://tinyurl.com/2yhv4wmx
  3. Miles Chou 的部落格:https://mileschou.github.io/
  4. Teddy Chen 的 Pattern based problem solving:https://www.slideshare.net/teddysoft/pattern-based-problem-solvingpublished
tags: ithelp2021

<<:  android studio 30天学习笔记-day 13-介绍databinding BindingAdapter

>>:  [Lesson13] OkHttp

入门魔法 - 变数宣告 let、const、var

前情提要 「我想确认一下,入门魔法都是加 100 魔力总量吗?」 艾草:「对唷!之後有中阶魔法加比较...

D33 - 用 Swift 和公开资讯,打造投资理财的 Apps { 台股申购功能扩充.4 }

处理申购 VC 的资料,是由 StockSubscriptionModel 处理的。 在前面,我们在...

Day 08 - Design System x 实作 — Color System

今天是这系列第一次碰 Code,要来介绍三种 Color System 在专案中实作的方式,但实现...

Day9 职训(机器学习与资料分析工程师培训班): python、 php结合highchart

上午: Python程序设计 老师此次课程教学for回圈, List comprehension, ...

从零开始用github架设静态网站入门(4) - 其他小功能制作

用之前的篇幅,已经大概跟大家介绍完静态网站的基本技巧,理论上要做出一个网站是没有什麽问题了,BUT我...