第二次博客作业

项目 内容
这个作业属于哪个课程 2021春季软件工程(罗杰 任健)
这个作业的要求在哪里 [个人阅读作业#2](个人阅读作业#2 - 作业 - 2021春季软件工程(罗杰 任健) - 班级博客 - 博客园 (cnblogs.com))
我在这个作业的目标是 学习软件开发的工程能力,参与软件开发的流程
这个作业在哪个具体方面帮助我实现目标 阅读《构建之法》;了解代码版控软件和持续集成方法

阅读提问

1. 为什么要在大学中只用一学期软件工程,时间够吗?

我翻阅了一下邹老师的这本书,觉得把软件工程的东西讲得十分深入浅出。

但是觉得只用一个学期的时间,就想把诸如个人开发、结对编程、团队开发,以及其中的Scrum/Sprint、MSF等开发方法学明白,是一件十分需要时间磨合的过程。仅仅通过一学期的时间,代码量可能是达到了,但是时间不够,很多在软件开发过程中开发的问题还没遇到,导致对这门课程的重要性认识不足。

举个例子:我认为有很多上这门课的同学,只是把这门课当成《面向对象程序设计》那样的“编程课”。但是《软件工程》这门课显然不是“编程课”,着重看待代码写没写出来,然后提交上去万事大吉;而不是学习别人开发过程中的各种各样的,因实际工程上遇到的问题,而逐渐总结出来的方法论。导致很多学习这门课的同学不会去认真思考很多工程上要求的重要性,反而当成拖累写代码的累赘。

总之,出现这样的问题。一方面是大学教育中,学生普遍追求考核指标,教育在某种程度上与工业界脱节;另一方面,也是学习软件工程的时间太短,不会理解软件工程的重要性。

所以我认为,只在一个学期,通过上课这种方式学习软件工程是不足够的。应该在有了一定的项目经验之后,我们再来谈软件工程的东西。

总之,我的问题就是:是不是学软工的时间太短了,以至于偏离了这门课的目的呢?如果从大一开始,每个学期都进行软件开发、总结、方法论的学习,是不是更好呢?

2. 怎么将单元测试集成到自动测试的框架中?

这个只是我的个人的技术性的问题。

这个问题出自邹老师的博客[单元测试&回归测试](现代软件工程讲义 2 开发技术 - 单元测试 & 回归测试 - SoftwareTeacher - 博客园 (cnblogs.com))。

另一个重要的措施是要把单元测试自动化,这样每个人都能很容易地运行它,并且可以使单元测试每天都运行。每个人都可以随时在自己的机器上运行。团队一般是在每日构建中运行单元测试的,这样每个单元测试的错误就能及时被发现并得到修改。

有没有什么现成的方法或者工具来来进行单元测试自动化?因为单元测试需要全方位覆盖,如果工程量大的话,是不可能手动调参测试的。那么应该怎么做呢?

3. PSP中衡量软件开发的工作量和质量的指标是否合适?

这一部分是在邹老师博客[工程师的能力评估与发展](现代软件工程讲义 2 工程师的能力评估和发展 - SoftwareTeacher - 博客园 (cnblogs.com))中写到的:

软件开发的工作量和质量怎么衡量呢? PSP认为有下列4 个因素:

a) 项目/任务有多大?

说明项目的大小, 一般用代码行数 (Line Of Code, LOC) 来表示;也可以用功能点 (function point). 一个重要的指标是: 你在实际产品中写了多少代码, 不包括空行/注释行/单字符行 .

b) 花了多少时间?

可以用小时, 天,月,年来表示。一组人所花费的时间可以用 (人数*时间) 来表示,例如某项目花费了10个人·月。

c) 质量如何?

d) 是否按时交付?

但是从标准方差 (Standard Deviation) 来看, Al 的方差是5.3,而Bob 是1. 显然Bob 比Al 的交付时间要稳定得多。在团队工作中, 稳定,一致的交付时间是衡量一个员工能力的重要方面。

首先,代码量的权重在衡量任务量上,应该放在这样的地位嘛我承认,在没有一定的代码量的前提下谈论工作量是没有意义的,正可谓巧妇难为无米之炊。

但是有的情况下很多代码,尤其是前任刚走,下一任来接替运维,打开代码,发现满屏幕的“屎山”。而且令人表示尴尬的是,功能倒是完成的挺好。那么这样的代码究竟是算多少工作量的呢?

我还是认为这样的代码是低质量的。因为可读性差,别人不方便维护。

有的时候很多重复性的代码,可能写一个函数就能复用,这从代码规范的角度来说或许并不是那么好。

这里插入一个代码量考核的漫画,聊表一笑。

代码量考核漫画1

代码量考核漫画2

代码量考核漫画3

代码量考核漫画4

代码量漫画考核6

其次,从时间来说花费时间越多,真的就代表工作量越高吗?

这就不得不提,软件工程的鼻祖项目——“人月神话”。

IBM开发system 360操作系统的时候,遇到了debug一处,引入多个bug的问题。时间、资金被不断吞噬,成为商业悲剧。

首先,由于我们对项目开发的进度估计过于乐观,我们估计出来的工作量通常会低于实际需要的工作量,尤其是对测试所需时间的安排常常是进度估算失误的重灾区,这应该是很多有经验的开发者会在估时的时候乘以一个固定的系数的原因(1.5 或者 2 甚至 3)。其次人员和时间的关系并非总是反比的关系,如果任务属于可以完全分解的理想状态话,是可能达到人员越多时间越少的反比效果的,但是,任务越复杂也就越难以分解,那任务中的沟通需求就会占用更多的时间,甚至可能导致人员越多,项目所需的时间越长。进而可以得出结论:当进度落后的时候,无脑增加开发人手可能并不能加快开发进度,甚至有可能导致进度更加缓慢。向进度落后的项目中增加人手,只会使进度更加落后,这也被成为 Brooks 法则。

一个任务时间长,可能不仅仅意味着

以及PSP中很多这样的小瑕疵。可能有读者认为我在抬杠,怎么不去工地上打灰?但是我是想借此来表达我对PSP的一点小思考。

PSP的考核指标可能忽视了个人与团队之间的联系

我承认,如果你能按照PSP的要求严格要求自己,你肯定能成为一名不错的写代码的人,甚至成为代码大神。但是写代码能力强只是成为合格的dev的一部分,你必须为团队考虑,要从整个软件项目出发。这是dev在写代码的过程中必须时刻要求自己的。

我甚至可以冒昧的认为,这种团队合作能力,或者说是与团队别的成员“粘合”的能力可能比写代码还重要。

是的,有的时候,我写一个函数很讨巧,效率很高,天花乱坠。但是如果只有我一个人看得懂,那么后续的测试怎么办呢?后续的集成怎么办呢?后续的运维的人怎么办呢?难道只能当作“上古神代码”膜拜,祖宗之法不可变,反正能跑出来吗?那么我觉得这种“神代码”要不然要把注释写的明明白白的,要不然就换一个人能读得懂的代码。

所以不把写注释看作是个人的评价标准,是我不能理解的地方。

这不仅仅是代码规范的问题,也是关系着一个团队能否正儿八经做事情的问题。

4. 极限编程的思路真的很好吗?

这一部分是来源于[结对编程与双人合作](现代软件工程讲义 3 结对编程和两人合作 - SoftwareTeacher - 博客园 (cnblogs.com))。

如果…… 发挥到极致就变成……
了解顾客的需求很重要 每时每刻都有客户在身边,时时了解需求
测试/单元测试能帮助提高质量 那就先写单元测试,从测试开始写程序——TDD
代码复审可以找到错误 从一开始就处于“复审”状态——结对编程
计划没有变化快 那就别做详细的设计,做频繁的增量开发,重构和频繁地发布
其他好方法…… 发挥到极限的做法……

读到这一段,我的思考是:为何要采用发挥到极限的方法?

邹老师是通过“结对编程”这个案列来说明为何结对编程:

有人要问,既然代码复审能发现这么多问题,有这么好的效果,如果我们每时每刻都处在代码复审的状态,那不是很好么?事实上,极限编程(Extreme Programming - XP)正是这一思想的体现——为什么不把一些卓有成效的开发方法用到极致(Extreme)? 结对编程就是一个例子。

我们可以得出一个简易的结论:极限编程就是把卓有成效的方法用到极致的编程。

维基百科给出的描述也是相似的:支持者相信,这些在传统的软件工程中看来是“极端的”实践,将会使开发过程比传统方法更加好的响应用户需求,因此更加敏捷,更好的构建出高质量软件。

但是,说一千道一万,就以结对编程为例,为什么这个看起来这么香的东西在国内推不开呢?

我随便在知乎上搜索“结对编程”,便很容易查到有人对于结对编程这件事口吐芬芳:

结对编程

核心就是“屁用没有,光开会讨论、讨论开会了。”他之所以会有这样的感觉,在我看来,可能是因为他们的项目组为“结对编程”而“结对编程”。(插句题外话,我稍稍怀疑我们在软工课程中,为何而结对编程?——因为不结对编程拿不到分。😦 )

在我的感知中(因为还没有开始结对编程的实践),结对编程很容易发展成为:“我写代码,你玩手机”、“你没加分号”、“我写你看”、“我觉得这么写可以,可你却偏叫我这样写”、“两个人在不断讨论,集中不了注意力在问题上,只能把注意力放在说服对方上。”

这些情况都是很容易出现的。

所以我的问题就是,以结对编程为例来考虑极限编程:1. 什么时候应当结对编程?2. 什么时候就不该结对编程?3. 代码复审很重要,但是我们就应当无时无刻不在代码复审吗?4. 结对编程是否意味着就不必代码复审了呢?

什么时候应当结对编程

结对编程可以在复杂代码部分进行。

结对编程可以就是提高代码可读性的问题。一个人陪着另一个人一起编程,自然就不存在代码读不懂的问题,因为在写代码的过程中,读不懂随时可以互相讨论。

是的,我认为,结对编程的一个很好的品质就是“随时交互”。(但是我没有用“优点”而是“品质”,是因为我认为这个特性不一定什么时候都是好的,我会在下一部分详细写一下。)

结对编程可以在开发者不熟悉的领域进行。

这就是经典的学徒制度。老师傅带着小徒弟。

(有的同学认为这样会降低老师傅的效率,给老师傅扯后腿。我不这么看。
从团队的角度出发,制约一个软件完成时间的很大的因素,就是完成最慢的那个组件。在这里完全是短板效应,你写的再快,小徒弟的组件没有完成,你也集成不了。耽误你的这点效率,在团队上来说是稳赚不赔的。)

让开发者考虑清楚每一行代码的意义,在他人指出问题之前,自己先审核一遍。

这有利于提高今后代码的质量。

什么时候不该结对编程?

疲劳的时候:

疲惫的时候很容易出现光讨论,讨论不出结果的问题。因为结对编程意味着两个人需要不断地对代码进行审核,这个过程是很累的。

进行前期的架构设计的时候

因为结对编程不能够对于一系列系统性的东西提出解决方案。结对编程适合解决已经“明确”的问题,适合“实现阶段”,比如:这里有个bug,我该怎么解决?、Hello World我打印不出来,应该怎么办?

两人思路不一致无法说服对方的时候

光吵架了,当然解决不了问题。

结对编程可以取代代码复审吗?

No!

结对编程是绝对不可以取代代码复审的。然而有的人就要问:结对编程就是代码复审发挥到极致的编程啊,为什么不能取代代码复审?

我们从哲学的角度出发(大雾),马克思说过:量变产生质变。在我看来,结对编程就意味着代码复审发生了质变。

什么是代码复审?来自在于邹老师的[代码规范&代码复审](现代软件工程讲义 3 代码规范与代码复审 - SoftwareTeacher - 博客园 (cnblogs.com))。

复审的目的在于:

(1)找出代码的错误。如:

a. 编码错误,比如一些能碰巧骗过编译器的错误。

b. 不符合项目组的代码规范的地方。

(2)发现逻辑错误,程序可以编译通过,但是代码的逻辑是错的。

(3)发现算法错误,比如使用的算法不够优化。

(4)发现潜在的错误和回归性错误——当前的修改导致以前修复的缺陷又重新出现。

(5)发现可能改进的地方。

(6)教育(互相教育)开发人员,传授经验,让更多的成员熟悉项目各部分的代码,同时熟悉和应用领域相关的实际知识。

结对编程会导致两个人的编程思想的趋同性,两个人共同编程、共同设计算法,就有可能共同掉进沟里。

前面的草蛇灰线、伏脉千里的“互相交互”就在这里了(大雾)。如果交互不那么频繁,对于代码不那么熟悉,反而是有助于代码中的错误和可能存在的问题的。但是结对编程已经产生了质变,它只能在小方向上纠错,如果遇到一开始的逻辑问题、算法问题等比较大的问题,是避免不了的。

同理,我们引用邹老师的表格:

如果…… 发挥到极致就变成…… 极致能取代如果吗?
了解顾客的需求很重要 每时每刻都有客户在身边,时时了解需求 两个人一直粘着,反而不知道最根本的需求是啥。只是把细碎的需求记载下来了,抓不住重点。
测试/单元测试能帮助提高质量 那就先写单元测试,从测试开始写程序——TDD 开发者只想完成测试,而忘记了测试的目的是完成需求。
代码复审可以找到错误 从一开始就处于“复审”状态——结对编程 略。
计划没有变化快 那就别做详细的设计,做频繁的增量开发,重构和频繁地发布 有可能导致低效率,很多功能因为设计不足而遇到问题,就需要重新设计并重构,改来改去。而如果设计文档写的很详细、很完备,只需要开发一次。
其他好方法…… 发挥到极限的做法……

总之,我的意思。不是说极限编程是垃圾,而是程序员必须脑袋里面有根弦:一个在这个问题上能提出很好的解决方案的方法,必然会在别的地方上引入新的问题。

工程,在我看来,就是妥协,就是具体问题具体分析。而不是教条一般地人云亦云。要明确什么情况好,什么情况不好。

事半功倍,这才是目的。

5. MSF的开发方式是不是也导致了微软在某些项目的失败?

比如:IE、edge、bing、 MSN、windows phone、Skype?(好吧,我承认这个问题是凑数的。)

调研源代码集成软件

  • gitlab: 本身开源,可以架设在自己的服务器上。
  • github: 上面的开源项目很多。且无空间限制。
  • bitbucket: 同时支持Mercurial,有免费的私有库,可支持别的Atlassian软件。

集成/部署工具:

gitlab cl:

代码库

使用maven重新构建项目,并编写简易的JUnit4测试:

(因为一部分的技术问题,所以集成测试的项目放在“oo_course_2020_16061020_exp_8”这个项目中)上传到gitlab上,并触发cl:

github actions

代码库

image-20210316213120361

总结

可能是因为我比较菜,所以我更喜欢gitlab ci,因为它的任务很明确,就是集成测试。github actions对我来说,还是有点难(汗),但是它通过各种插件来完成功能,更加灵活,而且每个workflow都分配一台虚拟机,这很酷。

第二次博客作业总结

啊,不知道为啥,写了好多。回头看看无关痛痒的废话不少233333333。这次博客作业,一方面我是靠我的阅读中的体会,另一方面遇到不会的问题也会去参考别人写的博客(才不是抄)。第一次觉得学习他人的经验可以让我稍微走的轻松一点。

然后也体会到gitlab ci的妙用。不过对我这种编程苦手,确实一开始学习yaml和maven有点吃力(才不会告诉你这是我的这辈子第一次用maven,全不会,只会抄。。。抄都抄不对)。

看了别的同学的博客可以用cobertura来测试覆盖度。。。嘛,因为马上就要截止了,所以就还没来得及学。不过应该挺有用的,之后的几天我应该会好好用功学吧。。。大概(摔)。

啊。。。这几天主要精力都用来写这份博客作业了。。。。结果才写了这么点233333333很担心接下来的软工怎么学呢,会不会把我这样的小菜鸡压死呢。。。

不过我想,认真地学习一下,哪怕最后结果不是很理想,也总归是学到了多少东西,对于之前的啥也不学习的我,多少来说算是一点长进。

优于别人并不高贵,真正的高贵是优于过去的自己。
——欧内斯特·海明威

啊,差点忘了,十分感谢赵博名助教同学的帮助,真的帮了大忙了。

posted on 2021-03-16 21:58  BuniQ  阅读(160)  评论(2编辑  收藏  举报