项目 | 内容 |
---|---|
这个作业属于哪个课程 | 2021春季软件工程(罗杰 任健) |
这个作业的要求在哪里 | 个人阅读作业 #2 |
我在这个课程的目标是 | 系统了解并参与软件开发过程,提升自身工程能力 |
这个作业在哪个具体方面帮助我实现目标 | 阅读《构建之法》,了解软件工程的概念,学习使用CI/CD工具 |
阅读提问
问题一:提高技能与熟悉解决低层次问题
那怎么提高技能呢?答案很简单,通过不断的练习,把那些低层次的问题都解决了,变成不用经过大脑的自动操作,然后才有时间和脑力来解决较高层次的问题。
——《构建之法》3.4 技能的反面
书中列举了定义数据类型、处理编译失败、设置断点调试等低层次问题。由此,我认为正确地调用方法也是一个低层次问题,但当方法各异、重载众多时,耗费时间和脑力来熟悉解决此问题,对提高技能真的有帮助吗?
我以
C++
容器和
Java
容器举例:
在
C++
中,列表、队列、集合添加元素的方法名各不相同,且均伴随着众多重载,
vector
为
push_back
,
queue
push
set
insert
。在
Java
中,问题有了明显的改善,前述三类容器添加元素的方法名均为
add
。
我认为,熟悉
Java
的程序员在学习以上
C++
类库时,只需要了解一个不同点,就意味着技能的提高。
Java
容器元素是引用;
C++
容器元素是拷贝,当将一个对象添加至容器中时,实际添加至容器中的是对象的一个拷贝,而不是对象本身。
以及,如今智能
IDE
普及,方法调用问题借助
IDE
即可解决,程序员真的有必要通过不断练习,将类库中的众多方法变为记忆吗?
问题二:注释
不要注释程序是怎么工作的,程序本身就应该能说明这一问题。
——《构建之法》4.2.9 注释
我曾在
Java
类库源码中看到过如下注释:
public abstract class AbstractList<E>
extends AbstractCollection<E> implements List<E> {
/**
* {@inheritDoc}
*
* @implSpec
* This implementation gets an iterator over the specified collection
* and iterates over it, inserting the elements obtained from the
* iterator into this list at the appropriate position, one at a time,
* using {@code add(int, E)}.
* Many implementations will override this method for efficiency.
*
* <p>Note that this implementation throws an
* {@code UnsupportedOperationException} unless
* {@link #add(int, Object) add(int, E)} is overridden.
*
* @throws UnsupportedOperationException {@inheritDoc}
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
* @throws IllegalArgumentException {@inheritDoc}
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public boolean addAll(int index, Collection<? extends E> c) {
rangeCheckForAdd(index);
boolean modified = false;
for (E e : c) {
add(index++, e);
modified = true;
}
return modified;
}
}
注释指出,
AbstractList
的
addAll
方法,通过迭代传入的
Collection
,并使用
add
方法,将每次迭代获得的元素添加至容器的恰当位置。这是否与书中提出的不要注释程序是怎么工作的这一观点相悖?
在实际开发中,当程序实现逻辑复杂,无法通过程序本身清晰体现时,如果不在注释中描述程序的部分实现逻辑,遇到不同的开发人员进行项目对接,如何保证对接的顺利和(未来可能)重构的高效呢?
问题三:goto
函数最好有单一的出口,为了达到这一目的,可以使用goto。只要有助于程序逻辑的清晰体现,什么方法都可以使用,包括goto。
——《构建之法》4.3.2 goto
在实际开发中,真的允许使用
goto
吗?这与我多年来受到的警戒和教诲严重相悖。
问题四:结对编程
在结对编程中,因为有随时的复审和交流,程序各方面的质量取决于一堆程序员中各方面水平较高的那一位。
结对编程让两个人所写的代码不断地处于“复审”的过程,程序员们能够不断地审核,提高设计和编码质量,可以及时发现并解决问题,避免把问题拖到后面的阶段去。
只有水平上的差距,没有级别上的差异。两人结对,尽管可能大家的级别资历不同,但不管在分析、设计或编码上,双方都拥有平等的决策权利。
——《构建之法》4.5 结对编程
可以看到,结对编程的重点在于使代码持续性地进行复审,这不免让人产生疑惑:
假设结对编程的两个人,一个人是新手,一个人是老手。如果新手编程,老手审核,新手的每一行代码都可能被老手进行指点和解释,势必影响开发效率;如何老手编程,新手审核,由于水平差距,新手又可能无法指出老手编程中的问题,势必影响审核标准。
通过检索,我了解到结对编程的通常作用是帮助新手快速熟悉业务逻辑和融入团队开发,这是否与书中与结对编程作用相关的阐释存在出入?
以及,在实际开发中,结对编程通常是以什么样的形式开展的呢?结对编程的两个人在技术栈、性格等方面有什么要求吗?
问题五:项目经理
成为一个合格的PM,需要哪些能力呢?——《构建之法》9.3 PM做开发和测试之外的所有事情
- 观察、理解和快速学习能力
- 分析管理能力
一定的专业能力
如果一定要说专业能力的话,PM的专业就是理解和表达,你能否理解不同人的心理、需求和言外之意。
PM通常也能写代码。
- 自省的能力
如上,书中总结了一个合格的项目经理应该具备的能力,提到了项目经理的专业是理解和表达。在知乎社区,我经常看到程序员吐槽项目经理,诸如提出的需求无法实现等。这是否源于项目经理对基本的开发流程和相关技术不熟悉?以及,项目经理是否也应该了解一定的开发技能?
调研源代码版本管理软件
相同之处
Gitlab 和 Github 都是基于 Git 实现的在线代码仓库,都建立了分享开源项目的平台,为开发团队提供了存储、分享、发布和合作开发项目的中心化云存储的场所。基于 Gitlab 和 Github 的团队协作流程相似:
- 发起人员建立源仓库,初始化永久性分支 master 和 develop ,添加团队开发人员
- 开发人员克隆源仓库,并创建自己的分支 develop-name
- 开发人员在本地仓库自己的分支下开发,提交 commit 并 push 至远端
- 开发人员提交 pull request 请求合并到 develop 分支
- 代码审查人员进行代码审查 ,同意将代码合并至源仓库
不同之处
Gitlab 让开发团队对代码仓库拥有更多的控制,相比于 Github,它有不少的特色:
- 允许免费设置仓库权限
- 允许用户选择分享一个 project 的部分代码
- 允许用户设置 project 的获取权限,进一步提升安全性
- 通过 inner-sourcing 让非权限范围内的人无法访问资源
从代码私有性方面来看,有时公司并不希望员工获取到全部的代码,此时 Gitlab 是更好的选择;但对于开源项目而言,Github 依然是代码托管的首选。
调研持续集成/部署工具
Gitlab CI
选取OOpre3Task3课程作业用于集成测试,利用 JUnit 4 进行单元测试
撰写
.gitlab-ci.yml
文件,并上传至仓库
Github Actions
仓库
总结
互联网软件的开发和发布,已经形成了一套标准流程,最重要的组成部分就是持续集成/持续部署。
持续集成的目的,是让产品可以快速迭代,同时保持高质量。它的核心措施是,代码集成到主干之前,必须通过自动化测试。只要有一个测试用例失败,就不能集成。
持续交付是持续集成的下一步,它强调的是,不论怎么更新,软件可以随时随地被交付。它的核心是,频繁地将软件的新版本,交付给质量团队或者用户,以供评审,如果评审通过,代码就进入生产阶段。
持续部署是持续交付的下一步,指的是代码通过评审以后,自动部署到生产环境。它强调的是,代码在任何时刻都是可部署的,可以进入生产阶段。
Gitlab CI 与 Github Actions 的对比见Continuous Integration Comparison。