2021年软工 个人阅读作业二
项目 | 内容 |
---|---|
这个作业属于哪个课程 | 2021春季软件工程(罗杰 任健) |
这个作业的要求在哪里 | 个人阅读作业#2 |
我在这个课程的目标是 | 熟悉软件工程的基本方法并尝试加以实践 |
这个作业在哪个具体方面帮助我实现目标 | 通读《构建之法》,对软件工程相关概念产生直观感受; 体验并熟悉 GitLab 和 GitHub 的CI/CD工具 |
全文约三千五百字,阅读时间大约6分钟。
一、针对《构建之法》的问题
在我大二时一些其他学校的同学跟我说软件工程一课十分空洞无物,每天都在写一些不知所云的文档,因此我本对《构建之法》不抱太大希望,但此书详实的例子和生动的讲解将难以直观感受到的敏捷开发方法形象地呈现在我眼前,使我对此有了较大的改观。通过粗略阅读,本人仍有许多疑惑与不解,故在此提出。
Q1:单元测试的构造与编写者问题
“代码的作者最了解代码的目的、特点和实现的局限性。所以,写单元测试没有比作者更适合的人选了。”
——《构建之法》第2章 个人技术和流程
从某种意义上来说这种方法有一定的道理。但是单元测试样例的构建与需求分析有极大的关联,样例大多由需求直接得来,按照本书中先进行单元测试样例的编写再进行业务代码的开发的顺序,重开发而轻文档的敏捷开发如何保证单元测试样例构造的合理性?开发人员负责自己模块单元测试的编写会不会造成需求上的理解性问题?
Q2:错误处理路径的单元测试覆盖问题
“单元测试应覆盖所测单元的所有代码路径,包括错误处理路径。”
“如果你的模块中的某个错误处理路径很难到达,那你也许要想想是否可以把这个错误处理拿掉。”
——《构建之法》第2章 个人技术和流程
“做过实际项目的工程师都知道,程序里的很多语句是用来处理种种异常情况的,这些情况大多都不会发生。但是若这些语句未被覆盖的话,这个模块的覆盖率就会下降,我就达不到80%的目标。所以我花了很多时间构造各种奇怪的测试数据,把程序中的那些犄角旮旯都尽可能覆盖掉。至于这些犄角旮旯在实际中是否会发生,对用户的影响如何,程序是否应该这样设计,我都不太关心。”
——《构建之法》第14章 质量保障
在这里我认为作者在某种意义上抛出了两种截然相反的观点,其一认为单元测试应该完全覆盖错误处理路径,若覆盖不了则应考虑删除该路径,其二认为为了达到覆盖率要求而花费大量时间构造错误处理路径的测试用例是不合适的做法。那么在实际的工程中对于错误处理路径的单元测试究竟应该提出什么样的要求呢?
在上学期的软件测试技术一课上,有一项作业便是使用某分析软件对某C代码片段进行单元测试并计算语句和分支覆盖率,在其中我们发现部分路径根本就不可能到达,而通过对源代码的阅读可以发现这个分支是由于可读性的要求或是防御性编程的策略而产生的,那么对于这部分分支又该怎样处理呢?此外,该课还提到了一种构建场景进行测试的方法,如用户从注册、登录、浏览、操作、退出的全过程,先构造正常样例,再分别构造在每一个步骤出错的样例,用这些样例对错误场景进行测试,是否这样的测试更加符合应用需求、更加合理呢?
Q3:结对编程的效率问题
“在结对编程模式下,一对程序员肩并肩、平等地、互补地进行开发工作。他们并排坐在一台电脑前,面对同一个显示器,使用同一个键盘、同一个鼠标一起工作。”
“这两个角色是可以互换的。和现实生活中的例子类似,一个人负责具体的执行(驾驶,用键盘编写程序等),另一人负责导航、检查、掩护等。”
——《构建之法》第4章 两人合作
作者认为这样的结对编程方式大有裨益,可以时时刻刻处于复审的环境之中,提高代码质量和开发效率,然而事实真的如此吗?现实赛车中的领航员和驾驶员分工明确且有严格定义的接口(路书),驾驶员可以仅凭领航员的指令进行驾驶,这与软件开发结对编程中的二人关系完全不一致。我认为代码的编写是一个需要沉思的过程,随时复审和交流会随时打断这一沉思,造成编码效率的下降和质量的下降。更何况从物理条件上,进行复审和单元测试样例构建的人同样可能需要写写画画,面对同一台电脑又如何能提供这样的环境呢?因此我认为将两人座位安排的较近(能直面交流),且有时间间隔地进行复审与交流比较符合实际。
Q4:敏捷开发中的时间预估与备案问题
“另一个改进是,要在每一个任务中记载我们完成这个任务还需要多少时间。已经花了多少时间虽然重要,但那不是关键(那是沉没成本),关键是要看我们离最后目标有多远。”
——《构建之法》第6章 敏捷流程
作者认为预估任务距完成所需的时间是一个重要的数据,需要进行预估,还提出了用燃尽图对任务进行跟踪的方式,这样的方式从理论上来说固然好,但我对其在实际开发过程中落地的效果如何表示疑问。敏捷开发每一步的流程均较短,这一特性对团队对时间的预估能力提出了较大的挑战,每一天的延后都会对敏捷效果产生比较大的影响,若对于开发时间估计不准备,燃尽图难免沦为形式,一推再推,一改再改。此外,由于敏捷开发对时间粒度划分较细,重视直接上手进行快速开发,若有底层或实现较为复杂的细节等难度较大的情况出现,又应该如何处理呢?
Q5:技术创新的关键性例证问题
在《构建之法》第16章 IT行业的创新一节中,作者使用“迷思之六:技术的创新是关键”作为标题并举出“铱星计划”手机的例子对这一观点进行了反驳。作者认为,“铱星计划”想法有很多不靠谱的地方,虽然技术上有巨大创新但用户量太少,最终导致了其不到一年时间就申请破产保护,成为了一项租赁业务。然而,这真的代表着技术创新的关键性有待考证吗?在我看来,这个例子恰恰正预示了技术创新的关键性。正是这种卫星通信手机的出现,才使得登山运动员、南极科考队员等群体有条件进行实时通话,完美地满足了他们的需求。而至于其商业上的失败,完全应该归因为其团队没有找准核心用户和核心场景,采取了不合适的商业模式,与其技术上的创新无关。
二、源代码版本管理软件调研
目前被广泛使用的基于源代码版本管理软件 Git 的项目管理工具有 GitHub, GitLab, Bitbucket 等,个人只对于 GitHub 和 GitLab 比较熟悉,经过调研,其一些异同之点如下:
2.1 相同之处
- 都基于 Git 这一源代码版本管理系统,能通过 git 相关指令进行版本控制
- 都允许在线上传、修改与 commit
- 都有社区功能,能对项目进行 star , 能对作者进行 follow 等
- 都能对项目提出 Issue
2.2 不同之处
GitHub :GitHub 是最早使用 Git 进行版本管理的托管平台,也是目前全球规模最大的源代码版本管理平台,其上托管了大量的开源项目,其中不乏 Linux、Nodejs 等知名项目,用户规模巨大,社区功能较为完善。但是它对于私有仓库有代码长度的限制,对私有项目不太友好。较为适用于开源项目的管理。
GitLab :GitLab是一个开源的、基于Ruby on Rails的源代码版本管理平台,可以自行部署。其相对于 GitHub 的一个重要优势便在于私有仓库免费,对于私有项目更加友好。此外其团队对成员的权限设置更加细致与明确。较为适用于私有项目的管理。
Bitbucket :Bitbucket个人没有使用过,部分报告提到其与 Atlassian 的一些软件配合较好。
三、持续集成/部署工具调研
由于OO课程原则上不允许开源作业代码,因此使用 Pre2_Task6 的源代码进行相关实验。
3.1 GitLab CI 实践
项目地址: https://gitlab.buaaoo.top/oo_2019_homeworks/oo_2020_preview2_18373584_pre2_task6
(注:我好像没权限把这个仓库设为 public,因此在下面直接给出 CI 有关代码,项目文件可于 GitHub 中查看)
首先在本地引入 maven 构建项目并针对 Ball
类编写单元测试,再根据教程和样例编写 .gitlab-ci.yml
文件,再次 push 便可触发 CI 流程,文件树如下图所示:
其中所用到的 .gitlab-ci.yml
内容如下:
image: local-registry.inner.buaaoo.top/image-dev/java:8u201
stages:
- build
- test
before_script:
- java -version
- javac -version
- mvn -v
- tree -a .
mvn_build:
stage: build
script:
- echo "Build project"
- mvn compile
artifacts:
expire_in: 2 hrs
paths:
- target
mvn_test:
stage: test
dependencies:
- mvn_build
script:
- tree -a .
- echo "Run JUnit4"
- mvn cobertura:cobertura
- mvn cobertura:dump-datafile
coverage: '/coverage line-rate="d+/'
artifacts:
expire_in: 2 hrs
paths:
- target
自动 build 与自动测试过程结果如下:
向 README.md
中增加覆盖率显示,结果如下:
3.2 GitHub Actions 实践
项目地址: https://github.com/gottfriede/TestCI
与上类似的,引入 maven 并编写单元测试,根据教程和样例编写 .github/workflows
文件,再次 push 便可触发 CI 流程,自动 build 与自动测试过程结果如下:
3.3 比较与看法
整体上而言,持续集成/持续部署方案将传统的打包构建、单元测试、上传发布等工作完全集中起来并进行自动化,使得程序员能从这些事务中抽出身来更多的关注代码本身,极大地提高了工作效率和效果。同时,这样的流程也符合敏捷开发的思想,使得频繁进行软件的交付成为了现实。
就本次 demo 的使用体验上来看, GitLab 的 CI 语法更为清晰简洁,对于流程更易于把握,而 GitHub Action 语法稍显繁琐。但是值得一提的是 GitHub 支持直接使用其他人开源的社区插件,对于一些常见需求的开发可以更简捷地满足,辅以 GitHub 巨大的用户基数,我认为 GitHub Action 在将来会有迅速的发展。
对一些 资料 进行查阅后,对一些其他重要特性的对比如下:
特性 | GitHub Actions | GitLab CI |
---|---|---|
可预测的定价 | 部分支持 分钟定价明确但计算成本复杂 |
完全支持 |
分布式构建 | 暂时没有提及 | 支持 |
报表与自托管 | 暂时不可用,但即将推出 | 支持 |
API支持 | 暂时没有提及 | 在CI需求上允许执行几乎所有操作 |