Xiaowu/20230411 (#791)

* Update 14.2 设计原则与实例.md

* update

* Update 14.1 设计原则.md

* Update 14.1 设计原则.md

* Update 14.1 设计原则.md

* update

* update

* update

* update

* update

* update

* update

* update

* update

* update

* update

* Update 5.0 开发流程.md

* yjklk

* update

* update

* asdasd

* Update 6.1 MSN的故事.md

* update

* jkl

* update

* asa

* kliig

* jkhkj

* update

* update

* uo

* update

* Update 7.7 第5步:需求技术分析.md

* update

* Update 7.7 第5步:需求技术分析.md

* Update 7.7 第5步:需求技术分析.md

* update

* Update 7.7 第5步:需求技术分析.md

* update

* jkh

* update

* Update 2.1 微软面试的故事.md

* update

* update

* update

* update

* jkl

* jffj

* jikj

* kjl

* update

* Update Slide45.SVG

* update
This commit is contained in:
xiaowuhu
2023-05-05 10:41:22 +08:00
committed by GitHub
parent fde8c65f6d
commit 7aee7e128f
448 changed files with 3201 additions and 3580 deletions
@@ -27,7 +27,7 @@
#### 感谢
郭百宁、Lily Sun、程、韦青、邹欣、沈园、董航、陈洋、贺秋时、吴淞芮、强红军
郭百宁、Lily Sun、程、韦青、邹欣、沈园、董航、陈洋、贺秋时、吴淞芮、强红军
@@ -1,8 +1,9 @@
<img src="img/Slide1.JPG"/>
(插入一些说明性文字,重点在介绍上下文,串连)
<img src="img/Slide1.SVG"/>
<img src="img/Slide2.JPG"/>
本章从一个软件工程的故事开始,木头带领大家一起初步领略了软件工程的复杂性。然后讲解了软件工程的基本概念及其相关领域学科。最后介绍了微软公司内的软件工程团队体系。
<img src="img/Slide2.SVG"/>
@@ -16,15 +17,8 @@
### 参考资料
1. 故事的原始情节来自于《构建之法》但是有所修改
2. https://en.wikipedia.org/wiki/History_of_software_engineering
3. https://en.wikipedia.org/wiki/Computer_science
4. https://ieeecs-media.computer.org/media/education/swebok/swebok-v3.pdf
### 参考资料
1. 《实用软件工程》第二版,郑人杰等,清华大学出版社
2. 《构建之法》,邹欣,人民邮电出版社
3. https://en.wikipedia.org/wiki/History_of_software_engineering
4. https://en.wikipedia.org/wiki/Computer_science
5. https://ieeecs-media.computer.org/media/education/swebok/swebok-v3.pdf
- Wikipedia,软件工程历史,https://en.wikipedia.org/wiki/History_of_software_engineering
- Wikipedia,计算机科学,https://en.wikipedia.org/wiki/Computer_science
- 软件工程 body of knowledgehttps://ieeecs-media.computer.org/media/education/swebok/swebok-v3.pdf
- 《实用软件工程》第二版,郑人杰等,清华大学出版社
- 《构建之法》,邹欣,人民邮电出版社
@@ -8,7 +8,7 @@
故事$^{[1]}$结束了......吗?刚刚开始呢!一系列“麻烦”在等待着木头。图 1.1.1 做了一个简单的“麻烦”预告。
<img src="img/Slide3.JPG"/>
<img src="img/Slide3.SVG"/>
图 1.1.1 木头遇到的麻烦
@@ -58,9 +58,9 @@
在学校出钱购买了 Azure 服务后,还付给了木头一小笔劳务费,木头笑纳了,但笑容很快就凝固了:五年级的老师知道了这件事情,希望系统能够出一元二次方程的题目。
家长们也纷纷表示一元二次的题目很便宜了,只需要0.5元一次,因为听说有的学校的方程题目要二元一次呢,贵了4倍!(哈哈哈哈,家长们很精明)
家长们也纷纷表示一元二次的题目很便宜了,只需要 0.5 元一次,因为听说有的学校的方程题目要二元一次呢,贵了 4 倍!(哈哈哈哈,家长们很精明)
另外,还需要能够提供7x24小时服务,学生随时可以申请“加餐”做题,而不是只有老师留作业的方式。
另外,还需要能够提供 7x24 小时服务,学生随时可以申请“加餐”做题,而不是只有老师留作业的方式。
木头又搞了几个周末,总算可以出解方程的题目了,并且提供了按需(On Demand)出题的方式。部署到云端后效果非常不错,觉得自己的贡献从一年级到五年级,非常值得!!!!!
@@ -69,6 +69,3 @@
基于微软 Azure 平台的出题系统非常成功,校长到处宣传,逢人便讲。一个国际学校的老师知道了这件事,联系到了木头,希望可以提供英文界面,便于外国学生使用。
木头感觉自己肩上的担子越来越重,那点儿劳务费还不够电费呢......没办法,硬着头皮上吧!后面指不定还有什么需求呢?
@@ -4,7 +4,7 @@
我们来分析一下故事的发展脉络,最终用公式的形式体现在图 1.2.1 中。
<img src="img/Slide4.JPG"/>
<img src="img/Slide4.SVG"/>
图 1.2.1 故事分析
@@ -109,7 +109,7 @@ $$
这样的话,木头就可以开一个软件服务公司了,名字已经想好了,叫做 WoodySoft,很洋气,哈哈。
<img src="img/Slide5.JPG"/>
<img src="img/Slide5.SVG"/>
图 1.2.2 软件解决方案
@@ -12,7 +12,7 @@
### 1.3.2 阶段任务(生存期 life cycle
<img src="img/Slide6.JPG"/>
<img src="img/Slide6.SVG"/>
图 1.3.1 软件工程包含的阶段任务
@@ -56,7 +56,7 @@
### 1.3.3 软件工程的基本目标
<img src="img/Slide7.JPG"/>
<img src="img/Slide7.SVG"/>
图 1.3.2 软件工程的基本目标
@@ -88,7 +88,7 @@
### 1.3.4 软件工程简史
我们用一张表简单地说明一下$^{[2]}$
我们用一张表简单地说明一下软件工程简史,见表 1.3.1。
表 1.3.1 软件工程简史
@@ -102,7 +102,7 @@
### 1.3.5 软件工程 vs. 计算机科学
我们先看一下计算机科学所涵盖的学科$^{[3]}$
我们先看一下计算机科学所涵盖的学科:
1. 理论计算科学(Theoretical computer science
- 理论计算(Theory of computation
@@ -147,7 +147,7 @@
简单的说,计算机科学是科学家、研究员们,发现规律、研究理论,并试图从根本上把规律理论化、公式化,不太在意成本,只在意效果。在图 1.3.3 中展示了计算机科学与软件工程之间的衔接关系。
<img src="img/Slide8.JPG"/>
<img src="img/Slide8.SVG"/>
图 1.3.3 计算机科学与软件工程的关系
@@ -4,7 +4,7 @@
我们在这一节中并不展开讲解,只是罗列一下知识领域(Knowledge Area),让大家可以粗略地认识到软件工程的复杂性,便于做好学习本书的充分准备。具体细节会渗透在后面的每一章节中。
<img src="img/Slide9.JPG"/>
<img src="img/Slide9.SVG"/>
图 1.4.1 软件工程知识领域
@@ -4,12 +4,12 @@
微软(Microsoft)是以提供软件为主要盈利手段的公司。描述像微软这样的软件公司的软件开发模式也可以使用几个公式。
<img src="img/Slide10.JPG"/>
<img src="img/Slide10.SVG"/>
图 1.5.1 微软的软件工程的组成要素(公式)
#### 程序
#### 1. 程序
$$
程序 = 算法+模型+数据结构 \tag{1.9}
@@ -19,7 +19,7 @@ $$
模型,一般是指机器学习或深度学习训练出来的 Model,里面既有逻辑又有数据,所以它既不是单纯的算法也不是单纯的数据结构。微软在 AI 领域的积累,使得很多程序都可以有模型的助力而变得“聪明”。
#### 软件工程师 SDE
#### 2. 软件工程师 SDE
在微软的程序员叫做 Dev(Developer,开发员)或者 SDESoftware Development Engineer,软件开发工程师)。
@@ -33,7 +33,7 @@ $$
有的人会问:在学校里学习的软件工程知识不够用吗?笔者只能说那些知识根本不够用,否则也不会写这本书了。
#### 项目管理 PM
#### 3. 项目管理 PM
$$
PM = 项目管理 + 产品管理 \tag{1.11}
@@ -43,7 +43,7 @@ $$
如何定义 PM 的工作呢?简单地说,凡是程序员做不了的事,都由 PM 来做。我们在后面相关章节会有说明。
#### 团队
#### 4. 团队
团队,在微软叫做 feature team,或者 feature crew。
@@ -57,7 +57,7 @@ $$
以前微软还有测试的职位,后来被取消了,由整个团队自己负责测试,并有自动化测试流程辅助。如果需要深度(手工)测试,就请外包测试人员来完成。
#### 软件工程
#### 5. 软件工程
$$
软件工程 = 团队 + 过程定义 + 执行 \tag{1.13}
@@ -65,20 +65,20 @@ $$
软件工程不只是软件工程师的事,而是整个团队的事。比如需求和过程管理要靠 PM,界面设计要靠 Designer。
#### 软件产品
#### 6. 软件产品
$$
软件产品 = 程序 + 软件工程 \tag{1.14}
$$
#### 软件公司
#### 7. 软件公司
$$
微软 = 软件产品 + 商业模式 \tag{1.15}
$$
<img src="img/Slide11.JPG"/>
<img src="img/Slide11.SVG"/>
图 1.5.2 微软的软件工程组成要素(树状图)
@@ -87,7 +87,7 @@ $$
商业模式不是本书的讨论范围,但是有三个概念要简单说一下:产品、项目、服务。
<img src="img/Slide12.JPG"/>
<img src="img/Slide12.SVG"/>
图 1.5.3 软件商业模式
@@ -96,11 +96,11 @@ $$
#### 产品
#### 1. 产品
我们以微软为例,产品包括:Windows、Office、Visual Studio等等,以客户端软件为主。其特点是由微软决定要做什么,给客户提供什么,具有长期规划,不断迭代。比如,微软认为Windows要提供给所有使用台式机的用户,Office要提供给白领办公人群,Visual Studio只提供给开发人员。每次更新,都是在现有基础上增加一些小的功能;而大版本号的更新则是提供了原有框架之外的功能,比如 Visual Studio 2019 提供了与微软云集成的众多功能,而这些功能在上一个大版本中并不存在。这些产品都是由微软内部专门的团队负责的,通常在500~5000人左右。
#### 项目
#### 2. 项目
项目包括两类:一种是狭义的,在销售给客户产品后,再同时开发/提供一些定制软件,比如银行买了微软的服务器和数据库,或者买了云资源,那么会有配套的开发人员进行售后服务,帮助银行开发产品。这种项目的研发人员一般比较少,10几个人就可以完成。
@@ -110,7 +110,7 @@ $$
注:在微软内部的技术术语中,功能都叫做 feature,可大可小,所以相应的团队叫做 feature team,翻译成中文很别扭,叫做“功能小组”。
#### 服务
#### 3. 服务
服务包括:Bing Search、Azure Cloud Platform、Office 365 等等,以云端服务为主,具有战略意义。当然要是把服务看作是存在于云端的产品,也是可以的。
@@ -121,7 +121,7 @@ $$
### 1.5.3 现实中的计算机科学与软件工程
一个很现实的问题是,计算机科学的本科和硕士毕业生在毕业后找工作比较难,除非一直学到博士毕业,才有可能加入一些大公司的研究机构当研究员,如 MSRAMicrosoft Research Asia,微软亚洲研究院)、阿里达摩院、百度研究院等等;而软件工程专业毕业的学生很容易找到程序员、工程师的职位,如 STCA(Search Technology Center Asia,微软亚洲互联网工程院)、BAT(百度、阿里、腾讯)以及很多中小型软件公司。
一个很现实的问题是,计算机科学的本科和硕士毕业生在毕业后找工作比较难,除非一直学到博士毕业,才有可能加入一些大公司的研究机构当研究员,如 MSRAMicrosoft Research Asia,微软亚洲研究院)、阿里达摩院、百度研究院等等;而软件工程专业毕业的学生很容易找到程序员、工程师的职位,如 STCA(Software Technology Center Asia,微软亚洲软件技术中心,既以前的工程院)、BAT(百度、阿里、腾讯)以及很多中小型软件公司。
但是对于另外一种论调,即“软件工程独立于计算机科学之外”,是因为近些年软件工程发展非常快,处于不确定性,要学习的知识和技能非常多,而计算机科学的理论基础成熟稳定,研究方向相对固定。
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 56 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 385 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 86 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 62 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 42 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 71 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 253 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 66 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 115 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 189 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 65 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 96 KiB

@@ -1,13 +1,7 @@
<img src="img/Slide1.SVG"/>
做一名合格的软件工程师所需要的专业技术能力有:
- 算法(algorithm
- 代码(coding skill
- 建模(design pattern
- 设计(system design
- 测试(testing
本章仍然以木头在微软的(真实)面试故事开头,讲解微软对软件工程师的要求,进而引入做一名合格的软件工程师所需要的专业技术能力,如:算法(algorithm)、代码(coding skill)、建模(design pattern)、设计(system design)、测试(testing)等。在最后,还列出了软件工程师的常见误区。
本章将会就这几个专业能力展开讨论。
@@ -17,8 +11,8 @@
### 参考资料
https://www.freecodecamp.org/news/how-to-think-like-a-programmer-lessons-in-problem-solving-d1d8bf1de7d2/
- 《构建之法》,邹欣,人民邮电出版社
https://www.jianshu.com/p/0f46896ab4a0
- 想程序员一样思考,Richard Reishttps://www.freecodecamp.org/news/how-to-think-like-a-programmer-lessons-in-problem-solving-d1d8bf1de7d2/
Krathwohl, D.R. (2002) A Revision of Blooms Taxonomy: An Overview. Theory into Practice, 41, 212-218. http://dx.doi.org/10.1016/S0164-1212(98)10055-9
- Krathwohl, D.R. (2002) A Revision of Blooms Taxonomy: An Overview. Theory into Practice, 41, 212-218. http://dx.doi.org/10.1016/S0164-1212(98)10055-9
@@ -1,3 +1,4 @@
## 2.1 面试的故事
我们先讲一个木头面试的(真实,但有节选)故事,从故事的情节中,大家也许可以发现像微软这样的公司是如何考察个人能力的。
@@ -15,17 +16,16 @@
某年 10 月 20 日,18:00 下班后,某大厦 4 层木头的办公地点。
```txt
木头的手机响了,一个男子的声音:我是微软 xxx,你是 yyy 吧?
木头激动地说:是!
面试官:我们进行电话面试吧?
木头:好。
面试官:您有大数据量的处理经验吗?
木头:有!每天上万条记录,一个月可以到 100 多万条,如,通话话单或短信业务......
```
*注:以上问题是关键,主要是看木头有无大批量数据的处理经验,所以可以初筛过关了。*
@@ -33,47 +33,45 @@
10 月 23 日,12:00 午休时间,某大厦 4 层木头的办公地点。
木头的手机响了,一个女子的声音:我是微软 zzz,你是 yyy 吧,我们可以电话面试吗?
```txt
木头的手机响了,一个女子的声音:我是微软 zzz,你是 yyy 吧,我们可以电话面试吗?
木头:好!
面试官:您先用英语介绍一下自己吧?
木头:blah blah blah......(磕磕绊绊的没关系,只要能说就行)。
面试官:给您出一道题目吧,也算智力题吧。
木头:好!
面试官:有一个101个单元的数组,在随机位置无回放地从1-100之间取一个数填入,最后一个空位随机填入1-100之间的任意一个数,求重复的数字是什么?
面试官:有一个101个单元的数组,在随机位置无回放地从1-100之间取一个数填入,
最后一个空位随机填入1-100之间的任意一个数,求重复的数字是什么?
```
*注:这是电话面试,如果你在电话这边一声不响地思考,那是不礼貌的,你必须尽快想出答案,并且在思考的过程中,要让对方“听到”你在思考。做到这一点很难。*
木头:嗯......(30秒后)用一个辅助存储数组,记录次数,最后统计一下即可。
```txt
木头:嗯......(30秒后)用一个辅助存储数组,记录次数,最后统计一下即可。
面试官:要是不用辅助存储呢?
木头:嗯......(30秒后)把数组排序,然后就能找到。
面试官:那要经过两次扫描,还有更简单方法吗?
木头:嗯......(30秒后)我暂时想不出来了,对不起。
面试官:没关系。再问您一个问题:如果有一款新手机,你打算如何测试?
木头:......(省略100字)反正我觉得重点应该在数据业务上,因为手机上的话音业务比较成熟,而数据业务是用户困惑的地方。
面试官:您有什么爱好吗?
木头:我喜欢游泳,我是业余中最专业的,但是专业中最业余的。我很幽默。我喜欢打桥牌,我喜欢玩魔方。
面试官:您很幽默,我听出来了。打桥牌,说明您逻辑推理能力强;魔方是个很有趣的爱好。
木头:是这样的(在电话面试的过程中,要尽量的表达你自己的优点,但不能过火)。
面试官:好的。如果合适,您还将接到电话。
木头:好的。
```
木头挂断电话,心里忐忑不安:唉!那个数组问题好像没答对啊!心里太紧张了,时间也太紧了,我讨厌电话面试这种形式。坐到座位上后,木头开始思考数组题的答案,10分钟后,有了结果,并且认为肯定是正确的答案之一。在电面过程中,不会有这10分钟存在的。估计我搞砸了,机会就这样远离我而去......
@@ -84,28 +82,30 @@
10 月 31 日 15:00,希格马大厦 6 层。
面试官是个小伙子:说说你最得意的项目吧。
```txt
木头:......(此处省略1000字。一般都是用这种方式开始,让面试者有个热身的机会,增加自信心)
面试官:咱们做个算法题吧,你在黑板上写出代码来!
```
*注:这个难度超大的,因为:1.站着;2.在黑板上写;3.有人看着。压力巨大。*
面试官:有两个数组,排序好的,分别有 M 个元素和 N 个元素,建立一个新数组,有 M+N 个元素,把那两个数组中的元素按次序写入新数组中,在写入的时候就排好序。
```txt
面试官:有两个数组,排序好的,分别有 M 个元素和 N 个元素,建立一个新数组,有 M+N 个元素,
把那两个数组中的元素按次序写入新数组中,在写入的时候就排好序。
```
木头 10 分钟后,涂涂改改若干次后,写出了一个函数,正要报告“完毕”,我忽然发现了一个漏洞,其中的一个数组有可能先用完,那么这段代码就会死机。又花了 2 分钟,把这个漏洞弥补上了。
挑了几个小毛病后,就进入第二问了。
面试官:还是这两个数组,从每个数组中取一个值相加,放入到新的数组中,在写入时就是排好序的,组合关系不能重复。比如,第一个组合是 $i_0+j_0$,第二个组合可能是 $i_0+j_1$ 或 $i_1+j_0$,取小的那个组合,然后继续......
木头:在黑板上做 $k=1,2,3$ 的推演,最后没有推出来,时间已经不够了......
面试官:$k=n$ 估计是时间不够了,咱们做一个建模题。三个形状,一个圆,一个矩形,一个正方形,如何建模?
```txt
面试官:还是这两个数组,从每个数组中取一个值相加,放入到新的数组中,在写入时就是排好序的,组合关系不能重复。
```
*注:比如,第一个组合是 $i_0+j_0$,第二个组合可能是 $i_0+j_1$ 或 $i_1+j_0$,取小的那个组合,然后继续......*
木头在黑板上做 $k=1,2,3$ 的推演,最后没有推出来,时间已经不够了......
```txt
面试官:k=n 估计是时间不够了,咱们做一个建模题。三个形状,一个圆,一个矩形,一个正方形,如何建模?
木头:......(此处省略1000字)
面试官:行,咱们去下一个面试吧。
```
*注:上面的第二问主要考你的解题思路,并不指望你能在现场解出来。回家后,我前后用了1小时时间,用代码实现了,保证是最佳算法。*
@@ -117,30 +117,27 @@
(算法!除了算法,还是算法!因为我应聘的是 SDE)
```txt
木头:(颤抖地)好...吗...吧!
面试官:有一棵满二叉树,每个节点都有一个指向其它某个节点的指针,要求用 $O(1)$ 的时间消耗,就能知道这个指针指向的是上级节点。如何设计数据结构?
面试官:有一棵满二叉树,每个节点都有一个指向其它某个节点的指针,要求用 $O(1)$ 的时间消耗,
就能知道这个指针指向的是上级节点。如何设计数据结构?
```
木头心想:数据结构的书没白看,这次有在黑板上写东西的经验了。3 分钟后,画了一个二叉树的数据结构,每个节点的 key 值都用含有级别信息的值标识,则任意一个节点内的指向其它节点的指针的 key 值与本节点的 key 值比较,就能知道指向的是否是上级节点。
```txt
面试官:还有没有更简单的方法?
木头:不可能有了。
面试官:真的吗?你用的是深度优先算法,能不能考虑广度优先算法?
木头:除非把节点存储在数组中,但是还要把左右节点也存到辅助数组中。
```
面试官站起来了,在黑板上刚把数组画出一半来,还没等他说话解释,木头立刻就明白了他的意思,说:哦,我知道了。满二叉树,第 n 级节点占用了 $2^n$ 个单元,用某节点的位置的单元序号直接能得到它的级别。
```txt
面试官:我们再出个建模题吧。大厦里有很多会议室,建个模型,来管理这些会议室。
木头:(先做了会议室类,再做了管理类)。
面试官:如果多人预订会议室呢?
木头:(又做了预订动作类)
```
又说了些别的,就带木头去 6 层了。他进去后和人力资源谈了几分钟,再出来时,就和木头握手说再见。人力资源说起下一轮面试的时间,木头才踏实了,知道应该过关了。
### 2.1.5 第五轮面试
@@ -149,35 +146,34 @@
面试官是个女博士,人很和善:说说你最得意的项目。
```txt
木头:您对增值业务有了解吗?数据业务或话音业务?
面试官:话音业务我不了解,说数据业务吧。
```
木头把数据互联网业务的系统设计思路在黑板上画了一遍,考虑到了可用性、可靠性、可扩展性,分 4 层结构,第一层做对内 DNS 轮询;第二层做接入,要用 Load Balance(负载均衡);第三层用 COM+ 组件,做中间件,做任务分发;第四层做数据库群集......(此处省略1000字)。
```txt
面试官:我们再做一个算法题吧。
木头:(天啊,又是算法)没...问题!
面试官:有一个字符集,要求用算法把所有组合列出来。如 ${a,b,c}$,要列出 ${a,b,c,ab,ac,bc,abc}$ 七种组合可能。
木头:(在黑板上写了5分钟,也没写出来)
面试官:可以考虑用递归方式
木头:我尽量先考虑用迭代方式吧。
面试官:好。
木头:(还是没琢磨出来)
面试官:再给你 5 分钟吧,写不出来就算了,我自己也写不出来。
```
木头:(5 分钟后写出了一个递归函数,勉强过关,她好像并不在意这个题目是否能答的出来,因为木头在开始的关于系统结构的讲解给她留下了很深的印象
木头 5 分钟后写出了一个递归函数,勉强过关,她好像并不在意这个题目是否能答的出来,因为木头在开始的关于系统结构的讲解给她留下了很深的印象。
```txt
面试官:咱们去 6 层吧,glad to meet you
木头:哦,好好(其实应该说 me too)。
```
*注:这种情景让笔者想起了有一次在Intel,给一个老外和几个同胞讲我们的产品系统结构,讲得他们很爽,最后老外主动站起来和我握手,说"glad to meet you"。当时,那些Intel的同胞都很惊讶的叫了一声,因为他们知道那个老外很少这样做,前面有10个这样的公司给他们讲东西了,他从来没有站起来过。于是我才知道,如果在刚见面时,人家对你说“glad to meet you”是客套,在会谈结束后说“glad to meet you”就表示是欣赏你。*
@@ -187,20 +183,20 @@
面试官是一个学者,应该是大领导,非常和善。
```txt
面试官:说说你最得意的项目。
木头:......(此处省略1000字)
面试官:你的简历中提到你的学习能力很强,说说理由。
```
木头说了木头第一次做语音增值业务系统的经过,又举了个自学游泳的例子):花 1 个月(4次)学仰泳,花 2 个月(8次)学自由泳,花 6 个月(24次)学蝶泳......
木头说了木头第一次做语音增值业务系统的经过,又举了个自学游泳的例子):花1个月(4次)学仰泳,花2个月(8次)学自由泳,花6个月(24次)学蝶泳......
```txt
面试官:当用户在网络上发起请求后,系统服务器故障了,你如何保留这个用户的请求信息。
木头:如果没有造成呼损,那就不管了;如果不牵涉到计费,也不管了;我尽量设计成把请求一次提交。
面试官:如果以上条件都不满足呢?
木头:那我只好把 session 存在 DB 里面了。
```
又说了些别的,就把木头送出办公室,挥手告别。
@@ -8,7 +8,7 @@
建模题一般就是考察面试者对事物的观察归纳能力以及面向对象的设计思想,这种设计仅限于对象级别的,稍微复杂一些的会涉及到组件级别,而非系统级别的。
#### 给一个会议室建模
#### 1. 给一个会议室建模
- 定义一个会议起止时间的帮助类
@@ -47,7 +47,7 @@ class Meeting():
给出了会议室的定义后,如果能够一鼓作气给出会议的定义,会更好,说明你思路清晰。因为有的面试者会误把会议的内容定义到会议室里面去。
#### 给一个十字路口的红绿灯系统建模
#### 2. 给一个十字路口的红绿灯系统建模
- 定义基本枚举值
@@ -98,7 +98,7 @@ class ControlCenter():
最后,每个十字路口都肯定会有一个中控器来控制四组灯的信号以保证其协调性。这一点往往是面试者容易忘记的,原因是他们并没有观察到有时候警察叔叔会手动操作中控器来控制交通流量。
#### 给一个魔方建模
#### 3. 给一个魔方建模
很多没有玩过魔方的人,会对此问题一筹莫展。在实际的面试时,可以要求面试官提供一个魔方,供面试者动手观察。
@@ -188,9 +188,9 @@ class RibukCube():
给魔方建模有几个误区:
- 从静态结构上把它分成上、中、下三层
- 从动作上多定义一个中心层的旋转
- 用颜色代替块的概念(颜色只是块的一个属性而已)
- 从静态结构上把它分成上、中、下三层
- 从动作上多定义一个中心层的旋转
- 用颜色代替块的概念(颜色只是块的一个属性而已)
如果有中心层,并且可以旋转的话,整个模型会变得非常复杂而不可描述,实际上中心层的“正向”旋转可以用两个边层的逆向旋转来表达,但是所谓的“正向”是无法定义清楚的,不像每个面那样可以把旋转 90 度和旋转 270 度区分开。
@@ -198,17 +198,17 @@ class RibukCube():
应用场景:
- 甲方每天早晨 8:00 传给乙方前一个交易日的股票大盘数据
- 乙方收到数据后,立刻验证数据是否齐备,然后使用已有模型做股票价格预测
- 需要在 9:30 之前把预测结果发送回甲方
- 甲方每天早晨 8:00 传给乙方前一个交易日的股票大盘数据
- 乙方收到数据后,立刻验证数据是否齐备,然后使用已有模型做股票价格预测
- 需要在 9:30 之前把预测结果发送回甲方
限制条件:
- 保存所有的历史大盘及预测记录
- 全自动化,无人干预
- 用微软 Azure 提供的技术
- 保存所有的历史大盘及预测记录
- 全自动化,无人干预
- 用微软 Azure 提供的技术
这个问题需要有一定的系统设计能力了
这个问题需要有一定的系统设计能力了,一个合格的设计如图 2.4.2 所示。
<img src="img/Slide8.SVG"/>
@@ -228,7 +228,9 @@ class RibukCube():
10. 控制中心同时通知甲方和乙方;
11. 甲方去约定好的地方下载结果到本地使用。
#### 关于存储
当然,这不是标准答案,实际上这个题目比较开放,有很多解决方案,也可以用任何模板图来绘制,主要考察应聘者对于系统的理解。如果时间允许的话,面试官可能还要考察你一些细节问题,让你描绘每个模块的内部功能、外部接口等等,如下面的内容所述。
#### 1. 关于存储
由于需要使用 Azure 技术(或其它公司的云服务),所以存储本身也是一个服务,而不是像传统的数据库或者磁盘文件那样还需要有一个本地的存取接口。
@@ -236,7 +238,7 @@ class RibukCube():
所以在这里我们可以使用 Azure Storage Blob 来存储大块的数据,速度快、容量大。
#### 关于控制中心
#### 2. 关于控制中心
这里一般存在两个误区:
@@ -247,7 +249,7 @@ class RibukCube():
而由于有云端存储服务的存在,所以上传、下载数据可以直接从客户端发起,而不需要网页服务,否则数据就需要从客户端传到网页上,在由网站转存到云端存储服务上,影响可靠性和性能。
#### 关于预测系统
#### 3. 关于预测系统
这个系统应该设计得很简单,对外接口是:
@@ -261,7 +263,7 @@ class RibukCube():
这里的设计误区是:预测系统和甲方、乙方直接有交互。由于预测所需要的时间很长,如果甲方误操作(比如连续多次上传数据并启动预测服务),预测系统将会不能正常工作。
#### 关于异常
#### 4. 关于异常
由于篇幅原因,在图 2.4.2 中没有做一些异常检测及处理,这也是考察面试者的重要因素。比如:
@@ -271,3 +273,17 @@ class RibukCube():
4. 预测过程中出现异常时,如何通知甲方或乙方?
关于设计,可以考察的形式和内容很多,也许面试官要求做以下的设计实例:
- 高并发的设计
- 异地灾备的设计
- 消息队列的设计
- 微信系统的设计(点对点通信)
- 微博系统的设计(消息订阅,发布)
- 淘宝系统的设计
- 异地访问延迟
- 高性能的理解和应用
- 微服务的使用
- 语音系统的设计
- 地图系统的设计
这就要求具有一定经验的应聘者平时要多观察、积累这方面的经验。而对于刚毕业的学生来说,这些东西有些勉强了,还是以基本的算法和编码能力为主。
@@ -2,7 +2,7 @@
### 2.5.1 定义、级别、角色
#### 定义(Definition
#### 1. 定义(Definition
微软是这样定位软件工程师的(英文原文):
@@ -14,7 +14,7 @@
- 定义并实施产品和服务的质量标准,通过有效的衡量手段和细致入微的观察来理解和验证用户体验的质量。
- 管理和改进工程过程,管理风险,捋顺依赖链条,必要时采取折中方案,将软件集成到更广泛的生态系统和/或产品和服务中。
#### 阶段(Stage
#### 2. 阶段(Stage
微软的软件工程师的阶段划分(级别)如图 2.5.1 所示。
@@ -37,7 +37,7 @@
......
#### 职业(Discipline
#### 3. 职业(Discipline
Discipline 原意是知识领域,可以引申为职业。前面也说过,在微软与软件开发有关的有以下几种主要的职业角色:
@@ -45,7 +45,7 @@ Discipline 原意是知识领域,可以引申为职业。前面也说过,在
- PMProgram Manager)项目经理
- Designer 设计师
#### 角色(Role
#### 4. 角色(Role
有三种角色:
@@ -89,7 +89,7 @@
这里有一个正例和一个反例,我们先说正例吧。
#### 正例:必应搜索中的 Instant Answer
#### 1. 正例:必应搜索中的 Instant Answer
所谓 Instant Answer,就是一种搜索结果,与普通的只有“一个标题+一个URL+一段简短的内容片段”组成的搜索结果不同。如图 2.6.3 所示。
@@ -115,7 +115,7 @@
最后泛化的结果是,我们用同一个 Pipeline 通过泛化做了 200+ 个 Answer,让美国的同行目瞪口呆。
#### 反例:多智能体强化学习优化平台
#### 2. 反例:多智能体强化学习优化平台
下面我们说一个反例,这个例子在第五章还会讲到。
@@ -131,7 +131,7 @@
### 2.6.7 全栈工程师梦,多不如精
#### 全栈工程师
#### 1. 全栈工程师
全栈工程师是指掌握多种软件开发技能,并能利用这些技能独立完成产品的人。
@@ -162,7 +162,7 @@
**但是,全栈工程师的真正意义在于团队合作中,他可以有全局性思维,可以带领团队走最短路径,而不是一个人负责开发所有代码。**
#### 全流程工程师
#### 2. 全流程工程师
其实,阻碍软件产品顺利发布的主要困难并非所采用的技术本身,而是如何利用软件工程知识把用户需求准确、快速地转换成为高质量的代码。学习一门技术不难,掌握产品转换的技巧才是关键。前者是“死的”,后者是“活的”。
@@ -170,19 +170,19 @@
### 2.6.8 三十岁做管理,中年危机
#### 保持热情
#### 1. 保持热情
一般来说女性成熟得较早,而男性在三四十岁的时候正值当打之年,可以大展宏图。
笔者在微软美国总部出差的时候,见过很多白胡子大叔仍然激情四射地在写代码。这些人一直是属于生龙活虎的人,一直保持着对工作和生活的热情,一直在追逐自己的兴趣爱好,一直在处理一些比较有挑战的技术工作,这样就不会觉得自己会步入中年,感觉还很年轻,自然不会有危机感。
#### 保持积累
#### 2. 保持积累
笔者以前的一位在微软的领导,针对一些年轻人不断跳槽想尽快提高收入的现象,曾经这样说过:“让你得到财富的正确方法是积累,是每个月有稳定的收入汇入你的银行账户,而不是靠一夜暴富。”
在年轻的时候努力,有一些积累(无论是技术上的还是经济上的)的话到后面就不会觉得很困难,而随着经验的积累也会厚积薄发。如果说没钱买房子还可以靠银行贷款,那么知识储备可是没有“预支”或“透支”的说法,书到用时方恨少,债到还时方知多。
#### 保持好奇
#### 3. 保持好奇
要有新的追求的目标,学习新的知识,不吃老本儿,既可以让自己感觉到新鲜,也能够及时充电,也不会有什么危机感。
@@ -3,13 +3,7 @@
<img src="img/Slide1.SVG"/>
上一章我们讲的是专业能力,具备了那些专业能力就可以成为一个合格的软件工程师。但是,如果想往更高的地方走,就需要本章中所讲的认知能力的辅助。
在笔者看来,认知能力包括:
- 沟通能力
- 学习能力
- 解决问题的能力
- 系统化思维能力
上一章我们讲的是专业能力,具备了那些专业能力就可以成为一个合格的软件工程师。但是,如果想往更高的地方走,就需要本章中所讲的认知能力的辅助。在笔者看来,认知能力包括:沟通能力、学习能力、解决问题的能力、系统化思维能力等,这些都可以通过读者对自己的认知能力的培养来获得,基本上就是马克思理论中的实践-理论的循环,在中国古代叫做知行合一,也可以细化为:学习、思考、实践、抽象。
<img src="img/Slide2.SVG"/>
@@ -17,10 +11,6 @@
### 参考资料
- https://www.freecodecamp.org/news/how-to-think-like-a-programmer-lessons-in-problem-solving-d1d8bf1de7d2/
- 像程序员一样思考,Richard Reishttps://www.freecodecamp.org/news/how-to-think-like-a-programmer-lessons-in-problem-solving-d1d8bf1de7d2/
- https://www.jianshu.com/p/0f46896ab4a0
Krathwohl, D.R. (2002) A Revision of Blooms Taxonomy: An Overview. Theory into Practice, 41, 212-218. http://dx.doi.org/10.1016/S0164-1212(98)10055-9
- https://zhuanlan.zhihu.com/p/539798401
- Krathwohl, D.R. (2002) A Revision of Blooms Taxonomy: An Overview. Theory into Practice, 41, 212-218. http://dx.doi.org/10.1016/S0164-1212(98)10055-9
@@ -31,15 +31,15 @@ Nobody is an island. 没有人是一座孤岛。
沟通是双向的,是一个编码、解码的过程,要求你既会说又会听。笔者认为不存在单向沟通,因为那不叫作沟通,叫做信息发布。
### 3.1.2 沟通的最佳实践
<img src="img/Slide4.SVG"/>
图 3.1.2 沟通的最佳实践
#### 1. 基于观点的沟通
图 3.1.2 总结了沟通的最佳实践,包含 3 组 15 个建议。下面我们一一进行说明。
**1)表达深思熟虑后的观点**
### 3.1.2 基于观点的沟通
#### 1. 表达深思熟虑后的观点
表达观点时,要有理有据(虽然不能保证合情合理),不能道听途说地只说个结论,没有推理过程或者解释说明。
@@ -59,7 +59,7 @@ Nobody is an island. 没有人是一座孤岛。
乐队里有一位 C,自认为自己多弹了几年吉他,有一些演出经验,经常会长篇大论地写一些东西,搬出来一些不明觉厉的名词,最后总不忘加一句“这些都是我上学时就玩儿剩下的”。木头只好说:“大家看看老 C 的文字,观点完整、有理有据,请大家学习。” 确实,在“观点完整”上,C 确实做到了,但是**观点完整并不代表观点正确,有理有据并不代表合情合理。**
**2谨慎使用反问句**
#### 2. 谨慎使用反问句
完整地表达观点,是一种成熟思考、具有知识体系的表现。微信的出现其实是为了普通大众服务的,往往是三言两语说完就走,因为不具备完整表达观点的能力。
@@ -69,7 +69,7 @@ Nobody is an island. 没有人是一座孤岛。
但是,完整地表达观点经常会吃亏,因为言多必失,大概率会有漏洞。有些人就会抓住其中一个小漏洞,或者是一个语病、一个词汇来反驳。乐队里就有这么一个家伙,总是不好好说话,阴阳怪气的总用反问句,比如“这怎么会是性别问题?”、“你觉得这样做就是公平的吗?”,这些看似普通的反问句在上下文里的伤害极大,使得大家不能正常交流,最后被木头踢出了乐队群。
**3观点的“角度”与“高度”**
#### 3. 观点的“角度”与“高度”
在人类所在的三维空间中,当然会有“角度”的概念,同样是看一个巨大的物理实体,有的人只能看到它的左侧,有的人只能看到右侧。由此引申到对待一个问题的看法,不同的人会有不同的“角度”。但是,当有人和你沟通时用了“角度”这个词,尤其是领导,大概率是在说你的思考层次“高度”不够,而不是“角度”。为什么呢?
@@ -79,7 +79,7 @@ Nobody is an island. 没有人是一座孤岛。
你自认为从 360 度观察到了事务的本质,但是领导却是从 720 度(包括上下两个维度)做了更多的思考。所以,说“角度不同”只是给你一个面子,其实是“高度”的差别。
**4基于事实的讨论,而非立场**
#### 4. 基于事实的讨论,而非立场
观点的形成是由三个概念决定的:利益$\rightarrow$立场$\rightarrow$行为。
@@ -101,7 +101,7 @@ Nobody is an island. 没有人是一座孤岛。
很典型的情况是,面对一个关键技术问题,两个人各持己见互不相让,其背后的原因很可能是采用了谁的建议,谁就会在 promotion 的路上向前迈进了一步。有个实际的例子,木头在 Windows 组时,常听到很远的隔壁的两个同事 A 和 B 因为在 Edge 浏览器上做银行插件时究竟应该采用哪种技术方案而进行讨论,A 是一个 Senior DevB 是一个 SDE II。后来 B 得到了 promotion 到了 Senior 级别,在邮件通告中的罗列的一条理由就是:B 在该项目上贡献突出,在技术方案的选择上与同组的一名 Senior 级别的员工竞争而胜出。
**5简洁不发散**
#### 5. 简洁不发散
沟通时,每个观点完整是必须的,但是在其它方面要简洁,不要过于发散。
@@ -109,9 +109,9 @@ Nobody is an island. 没有人是一座孤岛。
但是有一些人又过于简洁,茶壶煮饺子,心里有话但是倒不出来。笔者听说有个同事在 Machine Learning 上很有功底,就跑去请教,结果对方说了一些不是关键点的信息,听得云里雾里的。可能在对方看来,“有些基本的信息我都不用说你自然应该明白”,于是直接进入了细枝末节。
#### 2. 注意沟通方式
### 3.1.3 注意沟通方式
**1婉转表达否定**
#### 1. 婉转表达否定
假设你和领导进行 1:1 的年终总结谈话,领导说:“你在这个项目里承担了一些重要的工作,技术能力很不错,但是在与同事进行技术讨论时,在说话技巧上还有一些进步的空间。”
@@ -119,7 +119,7 @@ Nobody is an island. 没有人是一座孤岛。
在《星际迷航》电影里,经常会看到这样的对话:船长说“把动力系统全部移到船头形成能量保护网”,操作员可能会说“Negative(不行),我们需要至少10%的能量储备用于随时做光速跃迁逃逸。” 此时用 Positive/Negative 就会比较客观婉转,给船长留了面子。
**2注意语气语调**
#### 2. 注意语气语调
俗话说“有理不在声高”。有些人说话的音量很大,像是在吵架;有些人语速特别快,通常需要听者在脑子里把话在重复一遍才能明白;还有些人语气比较强硬,不太会用词。
@@ -129,13 +129,13 @@ Nobody is an island. 没有人是一座孤岛。
2. 速度慢,还稍微有些结巴(当然这不是优点),不过反而能让人明白他在说什么。
3. 不和别人争吵,有不同意见时,他表达完自己的观点后,如果对方不同意,他就会说“行,那再回去研究研究吧”,这样不管最终谁对谁错,都给双方留了余地。
**3及时回复**
#### 3. 及时回复
如果需要较长时间的思考,也可以回复说“让我先想想,一会儿回复您”。
曾经有一位朋友(微软中国 ARD 的韦青老师)请笔者去给一个合资公司讲讲“微软的工程师文化”,因为笔者当时很忙,一时不能确定能不能讲好,或者是需要多长时间的准备,所以就在第一时间回复说“让我想想”。两个小时后,给予了对方肯定的答复,然后就在业余时间开始准备演讲内容(即本书中的内容),最后的演讲效果非常好,这才启发、激励笔者继续写完这本书,相信会得到很好的读者反馈。
**4面对面的讨论更加有效,慵懒的文字会产生误解**
#### 4. 面对面的讨论更加有效,慵懒的文字会产生误解
以前在办公室里听到某人打字速度很快(而且还大胆地使用了机械键盘)时,就知道这个家伙一定在用电脑微信聊天,因为写代码的速度不可能那么快。现在面对疫情,大家都采用了线上办公,每天进行大量的文字交流。有的人文字表达能力非常差,而且懒,自己头脑中是有上下文信息的,但是不在文字中表达出来,往往造成对方误会。
@@ -143,7 +143,7 @@ Nobody is an island. 没有人是一座孤岛。
还有一个特点是,一般的实习生在写字时都会带上一个“啊”字,比如:“是啊”、“我也不知道啊”、“就是那样啊”,听上去像吵架。因为“啊”字本身在说出来时是一个轻声的后缀,没有实际含义,但是写出来就变成了一个强调的重语气词,看上去很不舒服。
**5少用对抗思维,多用平行思维**
#### 5. 少用对抗思维,多用平行思维
同事之间,如果没有上述的立场问题作怪,就尽量“先扬后抑”,或者“少抑多扬”。
@@ -153,9 +153,9 @@ Nobody is an island. 没有人是一座孤岛。
这种技巧,是 B 先给了 A 一个较强的心理暗示:咱俩是一个阵营的。这样 A 就会表现出合作的态度。
#### 3. 沟通的误区
### 3.1.4 沟通的误区
**1说话不要绕弯子**
#### 1. 说话不要绕弯子
比如,有个同事建议:“快到年底了,美国那边要休圣诞节假期,所以我们不如等他们都休假回来后再一起讨论后续的安排。” 其实是这个同事的年假没用完,他想在 12 月底休两周的假,他不直说,却把美国人搬出来当挡箭牌。
@@ -163,7 +163,7 @@ Nobody is an island. 没有人是一座孤岛。
这听上去就是很为演出效果考虑的感觉,但是春节后再开音乐会的话,排练不好安排,大家过完春节刚刚来上班,不论是观众和乐手,心气儿都差远了。木头看出来了是因为他们的乐手凑不齐才会提这个要求,所以拒绝了这个小队长的请求,说:“你如果缺乐手可以向别的乐队借,没必要把自己小乐队的困难绕个弯子转嫁到整个演出上。”
**2相同的话不要重复说**
#### 2. 相同的话不要重复说
在工程师层面的沟通,不需要像在大街上聊天似的,为了增加亲密程度和聊天长度而说“车轱辘话”。车轱辘话出现的原因是:
@@ -172,7 +172,7 @@ Nobody is an island. 没有人是一座孤岛。
一旦出现车轱辘话,在说者看来好像是强调了刚才的观点,但是在听者看来会得到两个结论:这个人固执;他没别的理由了。这与说者想达到的目的正好相反。
**3不要乱用“沉默”的权力**
#### 3. 不要乱用“沉默”的权力
笔者在写本书的“用户与需求”部分时,曾经想要求一位以前共过事的 PM 一起写,就发了一封邀请邮件,但是却石沉大海。笔者也不好意思再追问,干脆自己写。笔者感到很不可思议的是,曾经和那位 PM 在项目最艰难的时刻共同努力,最终令项目得到了总部的认可,相当于一起“扛过枪、负过伤”的交情,为什么对方会沉默呢?
@@ -180,7 +180,7 @@ Nobody is an island. 没有人是一座孤岛。
同样的问题经常发生在同事或朋友之间的微信通信上,有的时候甚至一句“新年快乐”发过去却得不到半点儿回音。对于笔者来说,当对对方的行为或言语极为反感时,才会采用“沉默”这种“极端”手段。比如,笔者的一个同学出家当尼姑了,想让笔者捐钱给她所在的寺庙,笔者是无神论者,所以选择了沉默。所以奉劝那些容易忘记回复消息的读者们,要真正地把对方放在心上,在方便的时候第一时间回复对方,这样对方才能把你也放在心上。
**4不抱怨结果,要分析原因**
#### 4. 不抱怨结果,要分析原因
无效的沟通往往是从对糟糕的结果的抱怨开始的。
@@ -188,7 +188,7 @@ Nobody is an island. 没有人是一座孤岛。
家长在家庭中处于强势地位,不太注重沟通的方式。但是一般的公司领导会很注意这些细节,在上面这种情况下一般会说:“这次项目结果不太理想,应该还可以做得更好,你有没有自己分析过是什么原因造成的呢?” 这样拉开话匣子,会让对方可以接受。
**5不挑战别人的决定,而是提出建设性意见**
#### 5. 不挑战别人的决定,而是提出建设性意见
有一些对话经常会出现这个问题:“为什么这样做?”
@@ -198,7 +198,7 @@ Nobody is an island. 没有人是一座孤岛。
不论哪种场合,如果直接了当地把自己的“具有建设性”的意见说出来,会得到领导的赏识和同事的赞许。“建设性”这个词还是木头在学习桥牌时第一次遇到的,叫做“建设性应叫”,意思是对方表达了完整的观点后,应该在尊重对方观点的前提下,提出自己的一些局部差异化观点,或是完全不同方向的补充意见,来共同完善这个观点。
### 3.1.3 沟通能力的培养
### 3.1.5 沟通能力的培养
沟通的前提是要有输出,别人才能理解你,才能达到沟通的目的;也要有输入,才能正确地理解别人。一般人都可以做到输入(听),但是能力欠缺的人没有输出或者很少有输出,造成沟通障碍,据笔者观察,在一个团队中,这类人占比为 10%~20%,虽然他们不会影响整个团队的协作,但是却会影响个人的职业发展。
@@ -1,15 +1,15 @@
## 3.4 学习能力
## 3.2 学习能力
### 3.4.1 元能力
### 3.2.1 元能力
**学习能力**是一项元能力。元能力,就是提升其它能力的能力。而学习能力所学习的目标是**知识**和**技能**
<img src="img/Slide5.SVG"/>
图 3.4.1 能力
图 3.2.1 能力
**知识**是人类从各个途径中获得的,经过提升总结与凝练的对客观世界的系统认识。包括“事实知识、概念知识、过程知识、元认知知识”,在 3.4.3 小节中讲解。
**知识**是人类从各个途径中获得的,经过提升总结与凝练的对客观世界的系统认识。包括“事实知识、概念知识、过程知识、元认知知识”,在 3.2.3 小节中讲解。
**技能**是在获得相关知识的基础上,通过一定练习或实践而获得的某一领域的经验与技巧。包括“硬技能(技巧)、软技能(经验)”。“弹吉他”是一种硬技能,需要头脑清楚、双手配合灵活,但不一定要懂得乐理知识;“编曲”则是一种软技能,需要懂得丰富的乐理知识,当然也需要掌握编曲工具的使用方法。
@@ -36,7 +36,7 @@ $$
另外,对于 IT 行业有其特殊性:新知识、新工具、新方法涌现的速度远远超过其他行业。保持好奇、终身学习,才能不落伍。
### 3.4.2 Bloom's Taxonomy - 布鲁姆分类
### 3.2.2 Bloom's Taxonomy - 布鲁姆分类
1956年,美国的教育心理学家 Benjamin Bloom 本杰明·布鲁姆发现,美国学校的测试题 95% 以上是在考学生的记忆力,就相当于文科中的历史、政治、法律,这些东西都是已经发生的事件或者已经规定好的条条框框,没有任何商量的余地。
@@ -44,7 +44,7 @@ $$
<img src="img/Slide6.SVG"/>
图 3.4.2 布鲁姆分类
图 3.2.2 布鲁姆分类
布鲁姆是根据人的“认知过程从简单到复杂,由具体到抽象”这一规律来作为其教育目标分类理论依据的。教育目标分类强调指导教学过程和对结果进行评价,用来判断学生对一个知识点的精通程度,从低层次的“记忆、理解、应用”,到高层次的“分析、评价、创造”。
@@ -156,7 +156,7 @@ $$
- 在已有的缓冲区的基础上,再设计一个二级缓冲区,可以容纳更多的数据,会成倍地提高查询的效率,但只付出很小的设备代价。
### 3.4.3 Knowledge Dimensions - 知识的难度分类
### 3.2.3 Knowledge Dimensions - 知识的难度分类
这一分类体系直译为知识的维度,但其实四个维度之间是有继承关系的,所以笔者把它翻译成知识的难度。四种难度的知识依次是:
@@ -167,7 +167,7 @@ $$
<img src="img/Slide7.SVG"/>
图 3.4.3 知识的难度
图 3.2.3 知识的难度
#### 1. Factual Knowledge 事实知识
@@ -180,7 +180,7 @@ $$
任何领域中的术语、具体细节和基本元素都可以定义为事实知识。比如软件和软件工程领域中的编程语言的语法知识、关于算法的名词知识(KNN、DNN、RNN、CNN......)、关于测试的各种名词知识(单元测试、集成测试......)等等。
是一种非常具像的知识形式,属于纯静态的问题。如图 3.4.3 中的子图 1,有 A、B、C 三个看上去独立的点,表示三个基本的事实知识。
是一种非常具像的知识形式,属于纯静态的问题。如图 3.2.3 中的子图 1,有 A、B、C 三个看上去独立的点,表示三个基本的事实知识。
学习这些静态知识最好的办法就是翻阅教科书,一般的书的作者都会比较严谨,在书中列出的名词及其解释会比较的准确和全面。然后再从其它渠道(比如互联网)获得更多的关于这些名词的实际应用的介绍,而不是机械地背诵它们的定义。
@@ -197,7 +197,7 @@ $$
- 原理和概括
- 理论、模型和结构
如图 3.4.3 中的子图 2,A、B、C 三个点扩展了其外延,使得本来独立的点连接到了一起,形成多个概念知识。
如图 3.2.3 中的子图 2,A、B、C 三个点扩展了其外延,使得本来独立的点连接到了一起,形成多个概念知识。
概念知识与低级别的事实知识相关,可以理解为是一种上下文相关的知识,而不是局限在某一个点(事实)上。比如我们知道了软件测试包括单元测试和集成测试这个事实(包含两个元素),但是还应该进一步知道它们分别侧重于哪个方面,区别和联系是什么。再比如算法名词,应该知道 KNN 是一种聚类算法,而 DNN、RNN、CNN 其实是深度神经网络中的一些名词,把它们结合起来可以形成强大的深度学习模型。
@@ -213,7 +213,7 @@ $$
注意,技能(skill)指的是人所具有的能力,不是所有人都有;技术(technique)指的是客观存在的东西,任何人都可以使用。具有这些知识并能够灵活运用是这个级别所要求的。比如如何实施单元测试,设计测试用例来覆盖各种情况是一种技能;而使用开发工具提供的单元测试的接口就是一种技术。
如图 3.4.3 中的子图 3,本来是静态联系,在 A 旋转起来后,发现 B、C 也跟着旋转起来,形成了齿轮组。同理,旋转 B 或 C 时,另外两个齿轮也跟着旋转。
如图 3.2.3 中的子图 3,本来是静态联系,在 A 旋转起来后,发现 B、C 也跟着旋转起来,形成了齿轮组。同理,旋转 B 或 C 时,另外两个齿轮也跟着旋转。
#### 4. Meta-cognitive Knowledge 元认知知识
@@ -227,24 +227,24 @@ $$
这个级别要求我们在充分掌握前面所说的三个层次的知识的前提下,你应该有自知之明,了解自己掌握了多少编程语言的知识、机器学习的知识、测试的知识,你在某个项目中还需要哪些技能才能胜任领导给予你的角色,你距离可以做一次讲座或者指导他人工作的能力还有多远。如果有差距的话,你可以准确地估计出还需要多长时间在哪个方向上的努力才能够达标。
如图 3.4.3 中的子图 4,在了解了前三层知识后,应该可以从它们“一生二、二生三、三生万物”地分解、模仿、理解、解释、甚至创造出一个齿轮箱。
如图 3.2.3 中的子图 4,在了解了前三层知识后,应该可以从它们“一生二、二生三、三生万物”地分解、模仿、理解、解释、甚至创造出一个齿轮箱。
### 3.4.4 当层次遇上难度
### 3.2.4 当层次遇上难度
3.4.2 小节和 3.4.3 小节是两个不同维度的的分类或分层,那么当这两个维度组合在一起,会发生什么事情呢?
3.2.2 小节和 3.2.3 小节是两个不同维度的的分类或分层,那么当这两个维度组合在一起,会发生什么事情呢?
<img src="img/Slide8.SVG"/>
图 3.4.4 二维知识/学习分类
图 3.2.4 二维知识/学习分类
图 3.4.4 就是二者结合的产物:
图 3.2.4 就是二者结合的产物:
- 在横向上,是知识学习的六个层次,从低级到高级;
- 在纵向上,是知识本身的难度,从具象到抽象。
在表格中用一些关键动词来表示具体行为,但是不够详细,所以表 3.4.1 是具体的解释。由于篇幅原因,把横表变成了纵表。
在表格中用一些关键动词来表示具体行为,但是不够详细,所以表 3.2.1 是具体的解释。由于篇幅原因,把横表变成了纵表。
表 3.4.1 二维学习/知识分类
表 3.2.1 二维学习/知识分类
||事实知识|概念知识|过程知识|元认知知识|
|-|-|-|-|-|
@@ -255,5 +255,5 @@ $$
|**评价**|评价一篇论文<br>的优缺点|确定各种采样<br>结果之间的相关性|判断各种采样<br>技术的效果|给一种负载分配<br>策略评分|
|**创造**|写一篇短文介绍刚刚<br>学习的神经网络知识|设计一个分类<br>体系把各种用户<br>需求区别开来|设计出有效的<br>项目工作流|提出学习深度学习<br>理论的方式|
有了表 3.4.1 的指导,我们可以准确地判断一个具体问题所处的层次、难度,也可以判断自己的能力所在的层次、难度。
有了表 3.2.1 的指导,我们可以准确地判断一个具体问题所处的层次、难度,也可以判断自己的能力所在的层次、难度。
@@ -1,4 +1,4 @@
## 3.2 解决问题的能力
## 3.3 解决问题的能力
关于“问题”这个词的定义有很多,在这里我们特指三类技术问题:
@@ -6,13 +6,13 @@
2. 要纠正的错误(Issue),比如:软件的输出和预期不一致、开发时间超过计划太多、用户量大时导致系统崩溃,等等。
3. 要解决的疑问(Question),比如:为什么井盖是圆的、为什么房子是方的、为什么在贪吃蛇游戏设计中应该使用链表,等等。
### 3.2.1 能力的评级
### 3.3.1 能力的评级
解决问题的能力高低可以有五级评价标准,下面我们采用倒序方法**从能力高到能力低**的顺序来讲述。
<img src="img/Slide9.SVG"/>
图 3.2.1 解决问题的能力评级
图 3.3.1 解决问题的能力评级
#### 阶段五:啥都不给
@@ -30,7 +30,7 @@
<img src="img/Slide10.SVG"/>
图 3.2.2 公交站点的聚类
图 3.3.2 公交站点的聚类
这里面就有很多坑需要木头自己填平,比如:
@@ -63,13 +63,13 @@
- 你的目标是要做公交站牌聚类;
- 我不知道现有的聚类算法是否可以直接使用,我们以前有个例子,是这样的:
如图 3.2.2,统计了几十个人的身高体重,但是粗心的统计员忘记记录性别了,此时,可以用聚类的办法来大致把这些点分成两类,一类是男性,一类是女性。具体的数据和代码你可以在咱们的代码仓库里 (https://github.com/microsoft/ai-edu)找到,当时我们使用 DBSCAN 算法实现的。
如图 3.3.2,统计了几十个人的身高体重,但是粗心的统计员忘记记录性别了,此时,可以用聚类的办法来大致把这些点分成两类,一类是男性,一类是女性。具体的数据和代码你可以在咱们的代码仓库里 (https://github.com/microsoft/ai-edu)找到,当时我们使用 DBSCAN 算法实现的。
但是,与公交站牌聚类的例子比较,可以看到二者的区别是:一个是在二维空间里的聚类,一个是在一维空间里的聚类,能保证聚类算法的效果是可信的吗?你需要做一些试验,来验证这一点。
<img src="img/Slide11.SVG"/>
图 3.2.3 人类性别聚类问题
图 3.3.3 人类性别聚类问题
所以,领导即告诉了目标,又告诉了相似的例子,木头需要写代码做试验,这比“给目标,给方法”的难度要稍微高一些。
@@ -93,7 +93,7 @@
- 在阶段四,只给“目标”,需要自己确定“范围”,通过寻找前人留下的“例子”来确定最终“方法”。
- 在阶段五,除了必要的资源以外“啥都不给”,“目标”靠自己来研究挖掘,能力高下立现。
### 3.2.2 木头遇到的技术问题
### 3.3.2 木头遇到的技术问题
有一个用户给木头报了一个 bug:在把 ONNX 模型从 32 位浮点精度转换成 16 位浮点精度的过程中,当使用单个样本做转换过程的测试时,很容易通过;但是当使用 32 个样本(作为一批)做测试时,基本上不能通过。因为转换过程会使用 GPU 以及内存资源,所以该用户猜测是多个样本带来了更多的资源占用,从而导致失败。
@@ -103,7 +103,7 @@
<img src="img/Slide12.SVG"/>
图 3.2.4 培养解决问题的能力
图 3.3.4 培养解决问题的能力
#### 2. 排查疑点
@@ -150,7 +150,7 @@ np.allclose(x, y, rtol=1e-1, atol=1e-2)
```
就可以轻松通过验证。由此可以得知就是精度问题导致验证失败。但是,如果就此得出结论“16 位的模型精度有问题”,那就为时过早了。
如图 3.2.4 所示,我们一直把怀疑集中到转换的过程,在 16 位精度的模型中,一个样本 S 做两次推理得到的结果 $Y$ 和 $Y'$,它们有时候和 $X$ 非常接近,有时候又不是很接近,而 $Y$ 和 $Y'$ 两者之间也会有精度差。
如图 3.3.4 所示,我们一直把怀疑集中到转换的过程,在 16 位精度的模型中,一个样本 S 做两次推理得到的结果 $Y$ 和 $Y'$,它们有时候和 $X$ 非常接近,有时候又不是很接近,而 $Y$ 和 $Y'$ 两者之间也会有精度差。
木头忽然想到:如果用 32 位模型做两次推理,得到的结果 $X$ 和 $X'$ 一样吗?于是得到试验结果如下:
@@ -190,7 +190,7 @@ np.allclose(x, y, rtol=1e-1, atol=1e-2)
【最佳实践】
在上面的过程中,木头经过了以下步骤来复现与理解问题,如图 3.2.5 所示:
在上面的过程中,木头经过了以下步骤来复现与理解问题,如图 3.3.5 所示:
0. 熟悉环境,这是对一些来到新环境的陌生读者开说的。
1. 复现问题,可以联系用户,让他们提供实测环境。
@@ -208,13 +208,13 @@ np.allclose(x, y, rtol=1e-1, atol=1e-2)
<img src="img/Slide13.SVG"/>
图 3.2.5 纠正错误的基本步骤
图 3.3.5 纠正错误的基本步骤
这个步骤/过程可以作为框架应用于绝大多数问题。其中,在排查疑点的过程中,大量地使用了“对比法”来寻找差异,而差异往往就是问题之所在。另外就是使用“分析法”,比如检查代码逻辑,通过日志看资源占用问题等。
### 3.2.3 提高解决问题的能力
### 3.3.3 提高解决问题的能力
#### 多学习,多实践
#### 1. 多学习,多实践
拥有更丰富的知识是解决一切问题的基本前提,最简单的比喻就是:如果想搬起更重的石头,就需要有更大的力气。所以,保持好奇,多学习各方面的知识,从容面对快速发展的计算机软硬件技术,对一个软件工程师来说非常重要。
@@ -222,7 +222,7 @@ np.allclose(x, y, rtol=1e-1, atol=1e-2)
关于实践,软件工程师有一句常说的话叫做“make your hands dirty”,直译为“把手弄脏”,引申为“亲自动手与尝试,获得第一手资料”,你只有切身复现与体会到一个问题的 pain point(痛点),才能深刻理解它,这是解决一切问题的前提。
#### 分析静态结构信息
#### 2. 分析静态结构信息
比如有面试官问:为什么井盖一般都是圆的?你可能会嗤之以鼻地反问到:那为什么房子都造成方形的呢?因为你可能会下意识地认为那就是一种习惯或者约定俗成而已,为什么非得要刨根问底儿呢?
@@ -236,7 +236,7 @@ np.allclose(x, y, rtol=1e-1, atol=1e-2)
有人会抬杠了:鸟巢就是圆形的,很多迪拜的建筑也都是圆形的。但是这些都是非典型建筑,而是标志性建筑。典型建筑都是方形的,即使外部是曲面的,内部空间也一定会分割成方形的。一是因为设计和建造成本才会最低,二是可以更有效地利用内部空间,三是符合三维空间法则,人们不容易迷失方向。
#### 分析动态行为习惯
#### 3. 分析动态行为习惯
这里有两个关于做饭的有趣的故事。
@@ -1,6 +1,6 @@
## 3.3 系统化思维能力
## 3.4 系统化思维能力
### 3.3.1 思维与系统化思维
### 3.4.1 思维与系统化思维
#### 1. 三个名词
@@ -8,7 +8,7 @@
<img src="img/Slide14.SVG"/>
图 3.3.1 三个名词的关系
图 3.4.1 三个名词的关系
**思考**,是一个动词,是人的大脑的一种能力和行为,就是程序员们常说的“等会儿!让我想想!脑子有点儿乱,这是我以前写的代码吗?这么丑!看上去很难理解......嗯,这个聚类算法并不适合于做有标签的数据分类学习,对吧?”
@@ -58,36 +58,36 @@
- 零和思维与双赢思维
- 零和思维(Win-Loss)是博弈论中的一个概念,博弈的双方,一方得益,另一方必然吃亏,此消彼长,二者相加总是为零。赌场中的庄家与赌客之间就是零和思维。在一个软件生态环境中的各路竞争对手也是零和思维。
- 零和思维Win-Loss)是博弈论中的一个概念,博弈的双方,一方得益,另一方必然吃亏,此消彼长,二者相加总是为零。赌场中的庄家与赌客之间就是零和思维。在一个软件生态环境中的各路竞争对手也是零和思维。
- 双赢思维(Win-Win)是双方合作的基础,在保持各自底线的前提下把竞争变成合作,获得各自的利益。微软放弃自己的 IE 浏览器,转而采用 Chromium 内核做 Edge 浏览器,是一种单方面的双赢思维,Google 对此当然是欢迎的,而微软得到的好处是站在巨人的肩膀上让自己看得更远。
#### 3. 从解决简单问题到系统化思维
先回忆一下 3.2 节中提到的“解决问题的能力”的主要内容。
先回忆一下 3.3 节中提到的“解决问题的能力”的主要内容。
通常来说,一个问题会包含有多个因素,这些因素都是**并列关系**,在拓扑结构上,如图 3.3.3 的**星形结构**。在某个特定条件下,只有一个因素会引发这个问题的出现。发现这个引发因素并加以解决,就是“解决问题的能力”体现。
通常来说,一个问题会包含有多个因素,这些因素都是**并列关系**,在拓扑结构上,如图 3.4.3 的**星形结构**。在某个特定条件下,只有一个因素会引发这个问题的出现。发现这个引发因素并加以解决,就是“解决问题的能力”体现。
而本节中的“系统化思维能力”所面对的问题,不仅仅是简单的一对一的因果关系,更多的是如图 3.3.2 中另外四种形式所示的复杂关系。所以,解决(简单)问题的能力也可以看作是一种简单的系统化思维能力。
而本节中的“系统化思维能力”所面对的问题,不仅仅是简单的一对一的因果关系,更多的是如图 3.4.2 中另外四种形式所示的复杂关系。所以,解决(简单)问题的能力也可以看作是一种简单的系统化思维能力。
<img src="img/Slide15.SVG"/>
图 3.3.2 系统化思维的几种形式
图 3.4.2 系统化思维的几种形式
**这些思维形式的形成,是因为系统(问题)本身就是这种结构**,而并非无中生有。“读万卷书行万里路”是形成系统化思维的必经之路,简单说就是见多识广。读书是为了增加理论知识,行路是为了增加实践知识。
**最终,形成系统化思维能力的目的还是解决问题。**
### 3.3.2 星形系统与思维形式
### 3.4.2 星形系统与思维形式
举一个比较通俗的例子:木头在某个级别上很长时间不能得到晋升,如何解决这个问题呢?
<img src="img/Slide16.SVG"/>
图 3.3.3 星形系统与思维形式
图 3.4.3 星形系统与思维形式
和解决技术问题一样,我们需要排查疑点,也就是影响晋升的因素都有哪些,如图 3.3.3 所示,它是一个星形的因果关系图。
和解决技术问题一样,我们需要排查疑点,也就是影响晋升的因素都有哪些,如图 3.4.3 所示,它是一个星形的因果关系图。
- 个人能力
@@ -131,7 +131,7 @@
OK,如果你能够从以上几个方面分析好自己当前的境遇,判断出哪一个因素才是“四年没有得到晋升”的关键,抓住重点,就能够“解决”这个问题,提高自己的晋升概率。
### 3.3.3 串行化系统与思维形式
### 3.4.3 串行化系统与思维形式
如果读者参观过现代化的汽车制造流水线,或者是任意一家现代化工厂,都会看到串行化系统的具体实例。我们常说的软件系统的数据处理 Pipeline,实际上就是借用这些串行化系统的概念。下面说说串行化思维形式。
@@ -143,9 +143,9 @@ OK,如果你能够从以上几个方面分析好自己当前的境遇,判断
<img src="img/Slide17.SVG"/>
图 3.3.4 北京有多少个加油站
图 3.4.4 北京有多少个加油站
正确的解题思路如图 3.3.4 所示,详细解释如下:
正确的解题思路如图 3.4.4 所示,详细解释如下:
#### 1. 北京有多少人口?
@@ -222,15 +222,15 @@ OK,如果你能够从以上几个方面分析好自己当前的境遇,判断
- 不能正确地解决每个依赖的问题,差之毫厘谬之千里。
- 堆栈较深(依赖链条长)时,没有信心/耐心继续下去。
### 3.3.4 金字塔形系统与思维形式
### 3.4.4 金字塔形系统与思维形式
在计算机硬件系统中,设计了各种各样的存储设备,这些设备成明显的层次结构,但是上小下大,介于串行系统与下面要讲的金字塔形系统之间,如图 3.3.5 所示。
在计算机硬件系统中,设计了各种各样的存储设备,这些设备成明显的层次结构,但是上小下大,介于串行系统与下面要讲的金字塔形系统之间,如图 3.4.5 所示。
<img src="img/Slide18.SVG"/>
图 3.3.5 金字塔形系统与思维方式
图 3.4.5 金字塔形系统与思维方式
先简单解释一下图 3.3.5 中的名词,见表 3.4.1。
先简单解释一下图 3.4.5 中的名词,见表 3.4.1。
表 3.4.1 存储设备列表
@@ -248,7 +248,7 @@ OK,如果你能够从以上几个方面分析好自己当前的境遇,判断
1988 年,知名组织理论家罗素·艾可夫(Russell Ackoff)在就任国际一般系统研究学会(International Society for General Systems Research)主席的发言中,提出了数据—信息—知识—智慧(DIKWData-Information-Knowledge-Wisdom)的知识三角形(知识金字塔)。
这个 DIKW 和图 3.3.5 所示的系统,在原理上是相通的:把下层的东西提取出精华来放在上层。比如表 3.4.2 所示的几种进化过程:
这个 DIKW 和图 3.4.5 所示的系统,在原理上是相通的:把下层的东西提取出精华来放在上层。比如表 3.4.2 所示的几种进化过程:
表 3.4.2 从数据到智慧的进化
@@ -260,13 +260,13 @@ OK,如果你能够从以上几个方面分析好自己当前的境遇,判断
金字塔形系统有时可以被串行系统或树形系统所代替。
### 3.3.5 树形系统与思维形式
### 3.4.5 树形系统与思维形式
树形多用于组织结构,虽然外轮廓也和金字塔形系统一样是三角形,不同的是,处于低层的元素不是同质的。
<img src="img/Slide19.SVG"/>
图 3.3.6 如何举办一场音乐会
图 3.4.6 如何举办一场音乐会
#### 1. 总体目标
@@ -320,21 +320,21 @@ OK,如果你能够从以上几个方面分析好自己当前的境遇,判断
- 从时间上看,以海报任务为例,设计、印刷、张贴、回收,是前后阶段顺序,每个阶段都需要有人、有场地、有方法、有工具才能完成。排练场地本身是一个空间,但是也需要时间的计划才能安排好很多组的排练。
- 从空间上看,以场地为例,舞台搭建的位置、音响布置的覆盖面、调音台中控的地点、有长度限制的线材的连接方式、观众的座椅位置、录音录像师的机位、乐器在舞台上的摆放位置、麦克风的排列形式,等等等等,都是需要联动考虑的问题。
### 3.3.6 环形系统与思维形式
### 3.4.6 环形系统与思维形式
环形系统,在生活中貌似不常见,但是其实人类本身就生活在一个环形的大自然环境中,虽然封闭但是可以自我修复,以达到最平衡的状态。古人总结出来的太极和五行理论就是环形系统。
<img src="img/Slide20.SVG"/>
图 3.3.7 环状系统的负反馈
图 3.4.7 环状系统的负反馈
先看一种比较简单常见的环状反馈系统。其原始系统如图 3.3.7 左上所示,只有“输入、信号处理、输出”三个环节。
先看一种比较简单常见的环状反馈系统。其原始系统如图 3.4.7 左上所示,只有“输入、信号处理、输出”三个环节。
但是经常有这种需求:当输出端电平太高时,需要输入端智能地调低电平,所以就在输出端增加一个采样点,把输出信号反馈给输入端,并在结合点上与输入信号电平相减(因为是负反馈),这样在输出端最终得到的就是一个相对平稳的信号。
在思考时,通常人们会认为自己的思想无比正确,主意无比美妙。但是当你说出你的主意并得到一些 feedback(反馈)后,会纠正你的一些错误想法,把这些信息加入到输入端重新思考,才会得到大家都认可的好主意。
还有一种比较复杂的形式,一个输入通常是经过了很多个环节处理,最后反馈回来,对最初的输入做矫正。如图 3.3.7 的右图所示的一个例子:
还有一种比较复杂的形式,一个输入通常是经过了很多个环节处理,最后反馈回来,对最初的输入做矫正。如图 3.4.7 的右图所示的一个例子:
1. 用户:“现在的系统运行有些慢,希望能够提升一下整体效率。”
@@ -347,23 +347,23 @@ OK,如果你能够从以上几个方面分析好自己当前的境遇,判断
本来是一个好的出发点,但是经过一个环状的系统走下来,反而事与愿违。用户在得到一个好处(运行性能提高)的同时,可能会等待更长的时间获得新功能,或者花更多的钱来购买设备。
### 3.3.7 网状系统与思维形式
### 3.4.7 网状系统与思维形式
网状系统(或者说是表格形式)思维是最复杂的一种形式,因为它涉及到了横向思维和纵向思维两个方向,甚至是多维的。而其它的思维形式都是单向的。
<img src="img/Slide21.SVG"/>
图 3.3.8 网状系统的负反馈
图 3.4.8 网状系统的负反馈
在软件开发过程中,如图 3.3.8 所示,从纵向看,通常是多个小组分别完成各自的子系统,每个子系统又包含一系列的模块。从横向看,不同子系统的模块组成一个端到端的功能。项目管理者在纵向上需要协调各个小组的进度,这样才能在横向上把不同子系统的功能串联起来,尽早得到一个可运行的系统。
在软件开发过程中,如图 3.4.8 所示,从纵向看,通常是多个小组分别完成各自的子系统,每个子系统又包含一系列的模块。从横向看,不同子系统的模块组成一个端到端的功能。项目管理者在纵向上需要协调各个小组的进度,这样才能在横向上把不同子系统的功能串联起来,尽早得到一个可运行的系统。
在机器学习中,通常有很多参数需要调节,比如深度神经网络中的步长值、样本批大小、卷积核的尺寸、正则化的参数等等,这些参数互相影响,网格状的参数搜索可以帮助我们找到最佳的参数组合。
在软件质量控制过程中,如图 3.3.9 所示,需要软件可以达到很多种质量指标,如:正确性、可靠性、易用性、高效率、可维护性、可移植性等等。但是其中的某些指标是相克的,一个指标的提升会带来另外一个指标的下降。
在软件质量控制过程中,如图 3.4.9 所示,需要软件可以达到很多种质量指标,如:正确性、可靠性、易用性、高效率、可维护性、可移植性等等。但是其中的某些指标是相克的,一个指标的提升会带来另外一个指标的下降。
<img src="img/Slide22.SVG"/>
图 3.3.9 质量指标之间的竞争
图 3.4.9 质量指标之间的竞争
在足球场上,教练会强调两点:一是全队三条线在横向上的步调一致,一起压上进攻,或者一起收缩防守;二是在纵向上,同一边的后卫、中场球员、前锋要协调进攻。在排球场上,六个队员形成 2x3 的网格阵型,兼顾进攻与防守。
File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 81 KiB

After

Width:  |  Height:  |  Size: 81 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 67 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 151 KiB

After

Width:  |  Height:  |  Size: 150 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 454 KiB

After

Width:  |  Height:  |  Size: 453 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 119 KiB

After

Width:  |  Height:  |  Size: 118 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 78 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 43 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 119 KiB

After

Width:  |  Height:  |  Size: 118 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 83 KiB

After

Width:  |  Height:  |  Size: 82 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 122 KiB

After

Width:  |  Height:  |  Size: 120 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 59 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 105 KiB

After

Width:  |  Height:  |  Size: 105 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 67 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 73 KiB

@@ -2,14 +2,11 @@
<img src="img/Slide1.SVG"/>
团队合作,主要指的是团队内部的成员之间的合作,双人的、多人的,同事之间的、上下级之间的,相同角色之间的、不同角色之间的,等等。
在本章的最后,还介绍了团队之间的合作,以及一种特殊的形式:实习生与导师之间的合作。
团队合作,主要指的是团队内部的成员之间的合作,双人的、多人的,同事之间的、上下级之间的,相同角色之间的、不同角色之间的,等等。本章中,描述了 6 种团队类型,木头会讲一个团队合作项目的故事,然后分析团队中的各种角色;接下来讲述了几种关系:个人与团队之间、团队与团队之间、实习生与导师之间的合作方法。
<img src="img/Slide2.SVG"/>
### 参考资料
- The Chicken and the Pig, Wiki Pedia, https://en.wikipedia.org/wiki/The_Chicken_and_the_Pig
@@ -20,3 +17,5 @@
- 什么是MVP? https://tsh.io/blog/mvp-app-and-the-other-validation-methods/
- 《实用软件工程》第二版,郑人杰,清华大学出版社
- 《卓有成效的敏捷》,史蒂夫·麦克康乃尔,人民邮电出版社
@@ -1,11 +1,11 @@
## 4.2 团队的类型
## 4.1 团队的类型
<img src="img/Slide4.SVG"/>
<img src="img/Slide3.SVG"/>
图 4.2.1 团队的阶层
图 4.1.1 团队的阶层
### 4.2.1 共同兴趣
### 4.1.1 共同兴趣
木头在小学时是上过音乐课的(不过好像所有人在小学时都有音乐课,所以木头也就失去了吹牛的资本,但那是木头唯一的一位音乐老师),每个同学都坐在一个右侧扶手即桌子的椅子上面,而音乐老师则坐在一架木制的旧钢琴后面,踩踏板发出的吱吱声音甚至比钢琴按键发出的声音还大。
@@ -20,17 +20,17 @@
- 高中的时候,开始听 CD,古典和轻音乐居多。
- 大学的时候,宿舍老五买了把吉他,结果老五没学会,木头(是老大)和老八学会了。对,一个宿舍住八个人。
- 毕业后,姐夫送了木头一把吉他,红棉的,木头开始自学弹唱,很难听。但是每到逢年过节,公司都会组织新年晚会,木头总会幻想着上台演唱,就会拿出吉他来在家嚎几嗓子,被家人称为“嚎哥”,然后不了了之。
- 直到有一天,木头发现在微软的同一个 Org 中工作的同事之中:
- 直到有一天,木头发现在微软的同一个团队中工作的同事之中:
- 有一个学吉他的,买了把 800 多块的木吉他,(当时觉得)音色很不错;
- 又发现一个吹小号的,以前是清华铜管乐队的;
- 还发现了一个喜欢唱歌又可以弹钢琴的;
- 以及一个吹笛子的。
于是,木头把大家召集起来,排练了一个《梨花又开放》,有口琴、吉他、笛子、小号、非洲鼓、沙锤、人声,一共 7 个人,终于在 Org 的元旦联欢会上第一次上台演出了!而且效果非常不错,台下掌声雷动。
于是,木头把大家召集起来,排练了一个《梨花又开放》,有口琴、吉他、笛子、小号、非洲鼓、沙锤、人声,一共 7 个人,终于在团队的元旦联欢会上第一次上台演出了!而且效果非常不错,台下掌声雷动。
这就是木头的第一支乐队,由一群具有共同兴趣爱好的人组成,每周的周四都会定时排练,然后在每个月底 Org 组织的 Happy Hour 上演出,因此叫做“星期四乐队”。
这就是木头的第一支乐队,由一群具有共同兴趣爱好的人组成,每周的周四都会定时排练,然后在每个月底团队组织的 Happy Hour 上演出,因此叫做“星期四乐队”。
如图 xx 左子图所示,共同的兴趣吸引了这些个人组成了临时团队(中间的大圆代表团队),如果没有了兴趣,则会离开团队,并且个人并不完全处于团队内部,有的人投入多,有的人投入少,也就是个人的圆圈与共同兴趣的圆圈的重叠面积。ta 们的大多数时间属于其它领域,因为靠兴趣并不能养家糊口。
如图 4.1.2 左子图所示,共同的兴趣吸引了这些个人组成了临时团队(中间的大圆代表团队),如果没有了兴趣,则会离开团队,并且个人并不完全处于团队内部,有的人投入多,有的人投入少,也就是个人的圆圈与共同兴趣的圆圈的重叠面积。ta 们的大多数时间属于其它领域,因为靠兴趣并不能养家糊口。
如果以软件行业为例,这种组织形式大概就是一个兴趣小组,几个朋友在在 GitHub 上开一个项目,业余时间贡献一下自己的力量,不需要什么规矩,也没有收入,大家都心照不宣,做事全凭热情。
@@ -38,17 +38,17 @@
《构建之法》一书中的“一窝蜂团队、业余剧院团队”属于这个级别。
<img src="img/Slide5.SVG"/>
<img src="img/Slide4.SVG"/>
图 4.2.2 共同兴趣与共同规则
图 4.1.2 共同兴趣与共同规则
### 4.2.2 共同规则
### 4.1.2 共同规则
“星期四乐队”这帮人不靠这个组织挣钱,只是想发挥特长,活跃气氛;也没有太多的规则,想排一个歌,大家同意就排,用什么乐器也没什么讲究,自己会什么就用什么。只是大家商量好,知道哪个同事过生日的话,就当天到 ta 的座位旁唱一首生日歌,以便发挥音乐的魅力来团结、感染每一个人。
后来,木头所在的这个 Org 被 lay off 了,木头还在可惜好不容易组织起的星期四乐队就这么没了吗?结果,Transfer 到 MSRA 后,正赶上 MSRA 成立三十周年的庆典活动准备,木头自告奋勇说要成立一支乐队,写一首 MSRA 研究院院歌,在庆典上演出。结果受到了领导的热情支持,给出经费买了一堆排练用的乐器、音响设备等等,再加上木头从星期四乐队带来的人马、乐器、设备,成立了 MSRA 乐队,后来改名为火星乐队(因为 MARS 和 MSRA 很相似)。
后来,木头所在的这个团队被 lay off 了,木头还在可惜好不容易组织起的星期四乐队就这么没了吗?Transfer 到研究院后,正赶上研究院成立三十周年的庆典活动准备,木头自告奋勇说要成立一支乐队,写一首研究院院歌,在庆典上演出。结果受到了领导的热情支持,给出经费买了一堆排练用的乐器、音响设备等等,再加上木头从星期四乐队带来的人马、乐器、设备,成立了研究院乐队,后来改名为火星乐队(因为 MARS 和研究院很相似)。
在庆典上的演出是一首原创歌曲,一首流行歌曲,也很成功,增加了木头的信心。微软北京西的其它 Org 中热爱音乐的同事们纷纷来加入,最终达到了 70 多人规模的微软乐队,在第二年就举办了第一届“微软乐队新年音乐会”。
在庆典上的演出是一首原创歌曲,一首流行歌曲,也很成功,增加了木头的信心。微软北京西的其它团队中热爱音乐的同事们纷纷来加入,最终达到了 70 多人规模的微软乐队,在第二年就举办了第一届“微软乐队新年音乐会”。
人多了,需要有一些规矩,不然这么多人的排练和组织会是一个大问题。最开始,有几个合得来的人自发组成了一个小乐队,也没有名字。木头说:你们带带其它人一起玩儿呗?他们回答说:带不动呀,我们就找几个有时间有激情有基础的就足够了。木头想了想,也对,他们只顾自己的小团体玩儿的高兴,那就随他们去吧。于是,木头找了几个有一定音乐基础和领导能力的人当队长,制定了如下规则:
@@ -65,7 +65,7 @@
所以**规则**比**兴趣**有更强的团队运行执行力,这是显而易见的,两个人虽然可以兴趣相同,但是行为习惯可能不同,必须用规则来约束。
如图 xx 右子图所示,看不见的规则像一条条纽带,把大家连接在一起形成一个团队,这些人之间没有明显的上下级关系,一般适合于比较小的团队。
如图 4.1.2 右子图所示,看不见的规则像一条条纽带,把大家连接在一起形成一个团队,这些人之间没有明显的上下级关系,一般适合于比较小的团队。
在软件行业中,这相当于在 GitHub 上建立了一个开源项目,一些不认识的人基于对项目的共同兴趣来贡献代码,建立社区。由于 Contributor 来自天南海北,所以有必要建立一些规则,比如:
- 公平讨论,技术领域没有长幼之分。
@@ -75,7 +75,7 @@
《构建之法》一书中的“社区团队”属于这个级别。
### 4.2.3 共同利益
### 4.1.3 共同利益
随着乐队的壮大,成员的身份也是五花八门,性别大概是一半一半,角色有工程师、PM、Designer、HR、行政助理、合同工等等,各人的背景经历、语言行为习惯也各不相同,这就会产生一些问题。
@@ -89,7 +89,7 @@
为什么利益比规则约束力强?因为利益一般都是指经济利益,人们为五斗米而折腰,不然就要饿死了。富二代不在此列。除了经济利益以外的那些不可衡量的“利益”,可以用后面所说的文化或信仰来解释。
如图 xx 左子图所示,团队中所有的个人都是围绕着共同的利益而行动,而个人与个人之间没有利益连接或利益冲突,适合于比较小的团队。根据个人贡献的不同,有的利益连接线比较粗,有的比较细,甚至是虚线连接。
如图 4.1.3 左子图所示,团队中所有的个人都是围绕着共同的利益而行动,而个人与个人之间没有利益连接或利益冲突,适合于比较小的团队。根据个人贡献的不同,有的利益连接线比较粗,有的比较细,甚至是虚线连接。
一些比较小的商业化乐队满足这种形式,租场地排练 -> 演出挣出场费 -> 养家糊口,如此循环。挣不到钱的话,又不具备后面所说的信仰的,那就会直接脱钩了。
@@ -105,11 +105,11 @@
《构建之法》一书中的“主治医师团队、明星团队、功能小组、爵士乐队”属于这个级别。
<img src="img/Slide6.SVG"/>
<img src="img/Slide5.SVG"/>
图 4.2.3 共同利益与共同文化
图 4.1.3 共同利益与共同文化
### 4.2.4 共同文化
### 4.1.4 共同文化
俗话说:小公司靠老板(以身作则,即规则执行)、中公司靠制度(规则 + 经济利益驱动),大公司靠文化(实际上是规则 + 利益 + 文化)。
@@ -122,7 +122,7 @@
靠文化来治理团队、组织和公司,比起规章制度来更加有效,也更聪明。因为文化本身不会强迫你做什么,而是潜移默化地让大家具有共同的思维方法和行为模式。你如果不同意公司的规章制度,你就必须离开团队;你如果不同意团队的文化,你可以继续留在团队,但是和大家没有共同语言。
如图 xx 右子图所示,它是一个树形的组织结构,外延是一个近似圆形的虚线圈,其含义是:
如图 4.1.3 右子图所示,它是一个树形的组织结构,外延是一个近似圆形的虚线圈,其含义是:
1. 虚线表示对团队内部有一定的约束力,但是不能避免个别人在边界上出圈儿,比如左侧的小老板和右侧的个人,都在边界上;
2. 不规则的圆形表示它可能在局部有些根据具体情况而做的调整,但整体上看是 OK 平滑的,没有毛刺。
@@ -139,7 +139,7 @@
忽然发现可以做大的企业的名称都是两个字的,三个字的名字念着别扭,四个字的名字别人就记不住了。
微软文化在这里
微软文化在这里
**Our mission is to empower every person and every organization on the planet to achieve more.**
@@ -169,22 +169,22 @@
- 三个月后,那位原部门领导 V 退休回台湾省了。
### 4.2.5 共同信仰
### 4.1.5 共同信仰
宗教组织、党政团体是属于这种类型的,信念坚定,精神力量强大,可以忍受肉体的疼痛而赴汤蹈火,万死不辞。
首先,这些人肯定是组织、有规则的;其次,ta 们所追求的利益不是个人利益,而是团体利益。文化在这类团体中并不重要。
如图 xx 左子图所示,如果与“共同文化”的图比较的话:
如图 4.1.4 左子图所示,如果与“共同文化”的图比较的话:
1. 外围是个标准的圆形,而不是局部可以扭曲的不规则边界,这表明了它的严格的约束力;
2. 本图的外延是一个实心体,基本没有空子可钻。
很多音乐人和商业化乐队在创办初期,入不敷出,凭着对音乐的热情与信仰,不顾亲人的劝阻,愣是可以坚持到出名。像朴树、许巍、赵雷、李健、汪峰,这些木头所敬仰的才华横溢的音乐人都是不到 30 岁时就已经崭露头角,但是更多的音乐人和乐队是为了信仰而殉葬的,ta 们的名字没人知道。正如朴树在《白桦林》里唱的:“天空依然阴霾依然有鸽子在飞翔,谁来证明那些没有墓碑的爱情和生命,雪依然在下那村庄依然安详,年轻的人们消逝在白桦林”,把歌词中的“爱情和生命”改成“音乐和信仰”就行了。
<img src="img/Slide7.SVG"/>
<img src="img/Slide6.SVG"/>
图 4.2.4 共同信仰与共同血脉
图 4.1.4 共同信仰与共同血脉
具有共同信仰的软件团队在软件行业很常见,比如很多的创业公司,他们跳跃了前面的“兴趣、规则、利益、文化”,直接拿“信仰”出来说事儿,和有共同信仰的人一同创业。
- 信仰是做事的宗旨、做事的目的、是企业的价值观。还记得那句“让天下没有难做的生意吗”?,就是这句话点燃了多少70、80后的热血,成就了一个网络王国。
@@ -194,12 +194,12 @@
《构建之法》一书中的“官僚模式、秘密团队、特工团队”属于这个级别。
### 4.2.6 共同血脉
### 4.1.6 共同血脉
这是团队的最高形式,这一点只有家族企业可以做到,企业内的领导者来自同一个家族,身体内流淌着相同的血脉,一荣俱荣,一损俱损。但是小企业还可以做到共同血脉,大企业中不可能要求员工也是共同血脉,那就灌输共同文化即可。
另外一种可能就是所话说的“土地庙里一起上过香的、庄稼地里一起插过秧的、抗日战争一起扛过枪的、解放战争一起受过伤的、战地医院互相输过血的、祖国建设一起运集装箱的”,这些人不但信仰相同,而且共同经历过生死考验,也可以看作是具有共同血脉。
这是一种最可怕的团队存在,无坚不摧,但有可能走向极端。如图 xx 右子图所示,它从外面看上去就是铁板一块,毫无空子可钻,团队规模通常比一般的团队要小(在图中表示为圆的半径较小),团队越大越有松散的可能。
这是一种最可怕的团队存在,无坚不摧,但有可能走向极端。如图 4.1.4 右子图所示,它从外面看上去就是铁板一块,毫无空子可钻,团队规模通常比一般的团队要小(在图中表示为圆的半径较小),团队越大越有松散的可能。
迄今为止,在软件行业中没有见过这类团队的存在,或者是存在但不著名。
@@ -1,22 +1,24 @@
## 4.1 团队工作的故事
## 4.2 团队工作的故事
下面讲一个真实的小故事,通过这个故事,读者可以了解到团队的成员组成以及基本的软件工程流程。
下面讲一个真实的小故事,通过这个故事,读者可以了解到团队的成员组成以及基本的软件工程流程。为了体现真实性,在下面的文字中有很多中英文夹杂的对话,这也是我司日常工作的常态,因为软件工程文化起源于西方,所以很多词汇用中文的话感觉不是很贴切,最常见的就是 bug 这个词,当用中文说“缺陷”的时候,听众通常反应不过来在说什么。
<img src="img/Slide3.SVG"/>
<img src="img/Slide7.SVG"/>
图 4.1.1 团队工作实例
图 4.2.1 团队工作实例
### 4.1.1 项目中的团队成员角色
### 4.2.1 项目中的团队成员角色
前一段时间木头接手了一个小项目:某金融公司与 MSRA 的机器学习组的研究员合作量化交易的研究。木头的任务是在 Azure 上开发一个系统,把数据上传、训练、推理、模型管理等组织起来并部署到 Azure 上,方便客户、研究员、管理者使用。
前一段时间木头接手了一个小项目:某金融公司与研究院的机器学习组的研究员合作量化交易的研究。木头的任务是在 Azure 上开发一个系统,把数据上传、训练、推理、模型管理等组织起来并部署到 Azure 上,方便客户、研究员、管理者使用。
本项目中涉及的人员有:
- 研究员、研究员 Lead、研究员 Manager
- 实习生、工程师、工程师 Lead、工程师 Manager
- 实习生、工程师、Tech Lead、工程师 Manager
- PM、PM Manager
- 微软方市场人员及商务管理人员
- 客户方技术人员和市场人员
- 方市场人员及商务管理人员
- 方技术人员和市场人员
微软方参与具体的 feature team 技术开发的成员是:
我司(乙方)参与具体的 feature team 技术开发的成员是:
- 研究员“大肖”
- 工程师“木头”
@@ -25,11 +27,18 @@
- 技术指导(Tech Lead)“大齐”
- PM “小P”
因为疫情原因,所以我们每周一次的例会都是通过 Microsoft Teams 软件在线上开的。木头负责系统设计和技术文档,当然也要写代码和测试,所以每次都是木头发出最新的技术文档供大家评审。评审反馈可以通过邮件,也可以在线会议时口头给出。
下面的故事中列出了几个小的讨论细节,便于大家了解真实的团队合作过程。
### 4.1.2 需求分析
### 4.2.2 每周例会
例会分为两种:内部的,外部的。
- 内部的例会只有技术人员参加,讨论技术方案细节。因为疫情原因,所以每周一次的例会都是通过 Microsoft Teams 软件在线上开的。木头负责系统设计和技术文档,当然也要写代码和测试,所以每次都是木头发出最新的技术文档供大家评审。评审反馈可以通过邮件,也可以在线会议时口头给出。
- 外部的例会,所有涉及的人员都参加,主要内容是:乙方的进度汇报,甲方的反馈,双方其它方面的信息同步。
### 4.2.3 需求分析
经过一周多的需求调研,木头列出了四个子系统的 Use Case(用例):
@@ -38,6 +47,8 @@
- 模型训练子系统
- 模型管理子系统
大家的反馈如下:
1. 石头同学给了5条反馈,其中第2条反馈是:“应该设计一个训练ID,用于连接上下文的唯一ID。”
*注:这个意见很重要,虽然不是需求阶段应该讨论的问题,但是说明石头同学已经开始思考实现细节了。*
@@ -50,9 +61,9 @@
*注:这也是对的,因为木头一开始就陷入了对训练和推理细节的学习和探讨,但后来发现重点不对,意识到这两个是独立子系统,是研究员负责的,只需要把它们当作黑盒子调用即可。果然得到 PM 的认可。*
经过这一轮的讨论,团队内部确定了系统架构和职责划分。
经过这一轮的讨论,团队内部确定了系统架构和职责划分。所以在这个阶段,工程团队这边只负责用户界面、推理。
### 4.1.3 技术选型
### 4.2.4 系统设计
这个系统中的技术点很多,每个点都有多种选择,需要团队讨论。木头印象较深的是推理机制触发的问题。
@@ -75,7 +86,7 @@
木头回复:
1. 我同意“修改 server 端的逻辑易行”这个 statement 是正确的,我的考虑是:
1. 我同意“修改 server 端的逻辑易行”这个 statement 是正确的,我的 concern 是:
- 即使服务器端有代码逻辑,我们也不能确定“用户上传数据的完整性”,除非有口头上的约定,我们根据这个约定来写代码;
- 如果服务器端不需要关于数据完整性判断的代码逻辑,则是最理想的状态,这种情况下完整性由客户负责。
@@ -85,31 +96,36 @@
小 P 也同意木头的意见。结果是,当客户听说可以自动化流程时,非常感兴趣,表示支持这个技术选型,下载使用那些 binary 文件也没有问题。
### 4.1.4 原型开发
### 4.2.5 原型开发
实际上原型开发就是为了验证技术选型。木头把整个系统的关键技术点分解出来,让大家认领,然后分别去验证。两个实习生被直接指派任务,去自己写代码做试验,然后回来汇报。实习生当然有权力发表自己的看法,但是面对复杂工程问题的时候,他们的实际经验并不多。
由于受疫情影响,实习生都是远程(在家)实习,每周汇报,所以木头并不能掌握他们的实际工作量是否饱满。果不其然,发现了其中一个实习生的问题:对 Azure 技术不太感兴趣,进展缓慢,但同时却参加了很多其他的学术/社会活动,没有专心在实习上。于是木头劝退了这名实习生,当然还会根据以前的表现考虑给与前半段的实习证明。
需要验证的技术环节包括
- 数据上传机制
- Azure Blob 的存储管理机制
- 用 Python 实现的 RESTful API 及 Web 监听机制
- VM(虚拟机)开关机制
- 远过程调用机制
- 邮件通知机制
需要验证的技术环节及负责人是
- 数据上传机制:木头。
- Azure Blob 的存储管理机制:木头。
- 用 Python 实现的 RESTful API 及 Web 监听机制:木头。
- 用 Python 实现的简单的网页:实习生。
- VM(虚拟机)开关机制:实习生。
- 远过程调用机制:实习生。
- 邮件通知机制:木头。
### 4.1.5 产品开发
### 4.2.6 产品开发
在原型中验证了上述各种技术环节后,进入了实际的开发阶段。实际的代码量并不大,而且可以复用原型中写的大部分代码。所以很快就完成了开发工作
由于模型训练子系统还是沿用以前旧的手工模式,而且每 60 个交易日才会训练一次新模型,而模型管理子系统直接采用一个第三方的开源软件,所以实际的工作在用户界面和模型推理上
### 4.1.6 用户文档
一旦在原型中验证了上述各种技术环节后,基本上也就解决了在系统设计中悬而未决的问题,所以大家也就没什么更多的意见了。进入了开发阶段时,实际的代码量并不大,而且可以复用原型中写的大部分代码,所以很快就完成了开发工作。
本方案中的关键点不是先进性、复杂性等等,而是可靠性,所以,系统越简单,可靠性越强。为此,木头进行了充分的测试。有一次不小心写错了一个测试逻辑条件,导致一个小时内发送了上百封通知邮件,但也恰巧验证了邮件服务的可靠性。
### 4.2.7 用户文档
开发完毕后,为了模拟真实的用户的客户端环境,木头特意找了一台 Windows 7 的机器,做数据上传和触发动作,没有发现任何问题。
然后木头写了一个用户文档,包括下载第三方软件并安装配置、路径设置、脚本运行方法等一系列操作的说明。小 P 根据这个文档做了一遍实际的操作,很顺利,就交给了用户。
### 4.1.7 系统切换
### 4.2.8 系统切换
一旦新系统上线,就有与旧的试验室系统并行或切换的问题。工程师石头负责旧的推理系统升级,以适应新的应用框架。
@@ -1,4 +1,4 @@
## 4.3 团队中的角色
## 4.3 故事分析-团队中的角色
### 4.3.1 故事分析
@@ -6,45 +6,45 @@
这样看起来,是不是微软的组织管理太过冗余了呢?我们看看下面的分析就知道了。
#### 研究员
#### 1. 研究员
研究员在前期的研究工作成果决定了这个项目是否可以通过工程化来履行合同,提供给最终用户。但是在软件工程实施阶段,他们处于顾问的地位,不会参与到设计与编码工作中。
#### 工程师
#### 2. 工程师
工程项目实施的主力,解决软件工程中所有的技术问题。在一段时期内(比如半年或两年),他们的主要时间都会花在这个项目上。质量好,速度快,下一年得到升职的机会就比较大。
#### 管理者
#### 3. 管理者
其实大家可以看到,在故事中各个管理者并没有参与技术讨论,实际上他们掌管的项目很多,没有时间精力参与到某个项目的细节讨论中来,只是在项目启动的时候定个方向,给成员们打打气。
在微软,这是司空见惯的,一线管理者不会参与到细节讨论。在一些小公司,有可能管理者直接参与到细节讨论,这也可能是因为中层力量薄弱,或者层级较少。
#### PM
#### 4. PM
PM 做项目管理,协调资源,掌控进度,与客户沟通,与公司内其它组织沟通,向上汇报等等。
#### 实习生
#### 5. 实习生
实习生在 Mentor(导师)的指导下,做一些被分解成单元的小任务,按照微软实习生的衡量标准,应该是可以完成的。但是实习生能不能写 Production(生产、上线)的代码,就不一定了,一般是导师把实习生的代码按照标准“包装”成生产代码。
#### Tech Lead 技术指导
#### 6. Tech Lead 技术指导
实际上这个角色在微软不常见,大家可以看到 Tech Lead 只是提出意见,并没有动手写代码。在这个项目中,Tech Lead 确实提出了很多自己的见解,有些是有用的,可以帮助提高产品质量的;但有些却是节外生枝的考虑,让每个环节的决策都特别困难,增加了工程师的工作负担。
但如上所述,最终的重大决定权在工程师,工程师可以参考 Tech Lead 的意见,但是不一定采纳,只要拿出理由来即可。
#### 市场和商务人员
#### 7. 市场和商务人员
他们在开始接触联系客户,签订合同,到后期执行时,不需要提出意见,除非是客户需求与合同不符。但是项目的任何进展都应该让他们知道,当他们有意见时,通常会直接给予管理团队,而不是给与工作团队。
### 4.3.2 动物餐厅的故事 v5.0
### 4.3.2 动物餐厅的故事 v6.0
猪和鸡的故事,想必大家不会陌生,中文有很多版本,在《构建之法》一书中也有提及,还有原始的英文的版本,只不过大家讲故事的细节有细微差别。笔者认为这个故事在团队建设中有很重要的指导作用,所以在本章中再次拿出来与大家分享。
猪和鸡的故事,想必大家不会陌生,中文有很多版本,在《构建之法》一书中也有提及,还有原始的英文的版本,只不过大家讲故事的细节有细微差别。笔者认为这个故事在团队建设中有很重要的指导作用,所以在本章中再次拿出来一个**升级版 v6.0**与大家分享。
蚂蚁、猪、鸡、狐狸、老虎、鹦鹉合伙开了一个饭店,具体分工见图 4.3.1。
蚂蚁、猪、鸡、狐狸、老虎、鹦鹉合伙开了一个饭店,具体分工见图 4.3.1。
<img src="img/Slide8.JPG"/>
<img src="img/Slide8.SVG"/>
图 4.3.1 动物餐厅的故事
@@ -52,7 +52,7 @@ PM 做项目管理,协调资源,掌控进度,与客户沟通,与公司
家族人数庞大,提供一道叫做“蚂蚁上树”的菜的原材料,每次都牺牲不少兄弟,算是用身家性命投入。一窝蚂蚁只能为一个餐厅服务,否则会入不敷出。
- 猪
-
身强力壮,老成持重,提供“鱼香肉丝”的原材料,身上满是伤口。一头猪只能为一个餐厅服务,否则会失血过多而失去恢复能力。
@@ -72,19 +72,18 @@ PM 做项目管理,协调资源,掌控进度,与客户沟通,与公司
老虎的朋友,能说会道,消息灵通,给老虎提供消息。鹦鹉每天自由地飞来飞去,随便吃几个虫儿喝几滴露水就饱了,餐厅经营得好坏与它没有什么紧密联系。
所以,对于我们每个人来说,都有如下规则:
所以,一个人:
- 有可能在无数的地方做鹦鹉,只要他有这个精力;
- 可以在很多的地方做老虎,只要他有这个财力;
- 只能在一个地方做狐狸,但是可以随时换到另外一个地方,只要他有这个人脉;
- 可以在一个以上的地方做母鸡,只要他有这个生产力;
- 不能同时在一个以上的地方做猪和蚂蚁,除非他有超能力。
- 不能同时在一个以上的地方做猪和蚂蚁,除非他有超能力。
【最佳实践】
*但是他们一般有一个原则: 重大决定由 “猪” 来定夺。*
*我们初入公司,公司肯定希望我们都是猪这类的,全身心投入到项目中去。我们的任务也就是做好“猪”的角色。*
- 有一个原则: 重大决定由 “大猪” 来定夺。
- 我们初入公司,公司肯定希望我们都是大猪这类的,全身心投入到项目中去。我们的任务也就是做好“大猪”的角色。
### 4.3.3 RASCI 模型
@@ -114,7 +113,7 @@ RASCI 是以下单词的缩写:**R**esponsible, **A**ccountable, **S**upportiv
这些人需要保持在在项目的整个生命周期中。由于他们作为项目利益相关者的身份或他们将受到项目影响的事实,他们需要在项目所包含的所有阶段(任务)了解进展情况。
<img src="img/Slide9.JPG"/>
<img src="img/Slide9.SVG"/>
图4.3.2 RASCI 模型
@@ -128,7 +127,7 @@ RASCI 是以下单词的缩写:**R**esponsible, **A**ccountable, **S**upportiv
|名称|角色|动物|
|--|--|--|--|--|
|A - Accountable|管理,掌管全局|狐狸|
|R - Responsible|负责,具体执行|蚂蚁,猪|
|R - Responsible|负责,具体执行|蚂蚁,猪|
|S - Support|支持,配合工作|母鸡|
|C - Consulted|顾问,决策支持|鹦鹉|
|I - Informed|知情,参考指导|老虎|
@@ -157,7 +156,7 @@ RASCI 是以下单词的缩写:**R**esponsible, **A**ccountable, **S**upportiv
前面我们一直强调的是任务,而不是项目。因为在软件工程中,在不同的阶段各类人员的角色是不同的。如图 4.3.3 所示。
<img src="img/Slide10.JPG"/>
<img src="img/Slide10.SVG"/>
图 4.3.3 RASCI 模型的应用
@@ -201,4 +200,4 @@ RASCI 模型明确了团队中的各个角色及其相关责任,为了在一
避免重复的任务或流程,有序安排有依赖的任务,有时还可以并行工作。
所以,在各个阶段,每个团队成员要认清自己的角色,该责无旁贷就不要推三阻四,该献可替否就不要沉默寡言,该作壁上观时就不要指手画脚。
所以,在各个阶段,每个团队成员要认清自己的角色,该责无旁贷就不要推三阻四,该献计献策时就不要沉默寡言,该作壁上观时就不要指手画脚。
@@ -1,19 +1,21 @@
## 4.4 个人与团队/小团队与大团队
## 4.4 个人与团队
### 4.4.1 木头的故事
#### 在 Bing 必应搜索团队
#### 1. 在 Bing 必应搜索团队
刚到微软工作时,木头在 Bing 团队中的一个小组工作。一切安好,但是到了第三年时,一个领导的出现改变了木头的职业道路。
当时的 report 关系是:木头 -> Lead A -> Manager B。每次 A 想提拔(promote)木头时,B 总说“还不够好”。木头可以肯定地说这是一种偏见,因为木头的同事坐在 B 的办公室门口的座位办公,听到过 B 曾经说“就应该用鞭子抽”。如果他的话有音频证据的话,可以保证 B 会卷铺盖离开微软。
A 人很好,总会安慰木头说“下次估计希望很大”,但下次 B 还是用同样的理由拒绝。就这样耗了两年,木头看情况不妙,赶紧 transfer 到了 Windows China 团队,结束了这场噩梦。
Lead A 人很好,总会安慰木头说“下次估计希望很大”,但下次 B 还是用同样的理由拒绝,但是同一个组工作的其它两个人,一个做界面的,一个做引擎的,都得到了一级升职。相比之下,木头是做 Pipeline 的,代码量是他们的 5~10 倍,但是 visibility 不如他们高。就这样耗了两年,木头看情况不妙,赶紧 transfer 到了 Windows China 团队,结束了这场噩梦。
到了新团队后,木头听说 B 给 A 升职了,看到通知邮件后,发现给 A 列出的那些业绩,前两条就是木头负责的项目。
#### 在 Windows China 团队
【最佳实践】这本来是一个好团队。领导是一个团队里的重要角色,几乎代表了团队的行事风格,ta 可以“说你行你就行不行也行”,也可以“说你不行你就不行行也不行”。尽管你个人和团队很融洽,尽管你做了大量的后台工作,但是决定命运的还是团队的领导。
#### 2. 在 Windows China 团队
木头在 Windows China 团队一干就是 5 年,晋升得也很顺利。忽然总部一个命令下来,让这 20 多号人去做手机上的 Edge 浏览器,而且是基于 Google 的 Chromium。我们只好放弃了手头将要完工的关于 Cortana 的工作,立刻开始学习 Android 和 iOS 上的移动开发。后来才知道,总部是在用我们这个小团队做试验,看看基于 Chromium 的浏览器开发是否可以达到令人满意的效果,以便决定是否要在 PC 上放弃旧的 Edge 浏览器引擎,采用 Chromium 做内核,开发新一代 Edge 浏览器。
@@ -23,11 +25,15 @@ A 人很好,总会安慰木头说“下次估计希望很大”,但下次 B
又是半年后,总部决定解散 Windows China 团队,因为它已经完成了“在中国建立 Windows 10 生态系统”的使命,团队成员要么拿着 N+2 走人,要么在公司内自己找职位 transfer。
木头选择了跟着老板 C 去 MSRA 做 IC,职位是 RSDE。
老板 C 在几个月前听到风声,就已经先跑路回到了研究院,还想拉木头一起过去,木头还很不情愿。到了现在,木头只好选择了跟着老板 C 去 研究院 做 IC,职位是 RSDE。
#### 在研究院的团队
【最佳实践】这本来也是一个好团队。不管一个团队过去的功绩如何,当遇到 Business Impact 时,决定是无情的。在这个团队中,木头逐渐从 IC 变成了 Lead,可谓一帆风顺。但是命运的安排会让人走上另外一条道路,塞翁失马焉知非福。另一方面,找到一个可以互相信任的老板是多么的重要。
刚到 MSRA 几周后,木头就感觉不对劲儿:因为这里都是研究员,而木头是工程师,大家的文化差异比较大,工作性质不同,career path 也不同,很难在这个组织中站(出)稳(人)脚(头)跟(地)。一年多后老板 C 回美国了,木头找机会又转到了 MSRA 所属的一个小的工程团队,这个团队包括老板在内只有 6 个人。
#### 3. 在研究院的团队
刚到研究院几周后,木头就感觉不对劲儿:因为这里都是研究员,而木头是工程师,大家的文化差异比较大,工作性质不同,career path 也不同,很难在这个组织中站(出)稳(人)脚(头)跟(地)。在这段时间里,木头有时间去学习 AI 知识了,像是打开了一个新的窗户,看到了一个新世界。然后把学习过程写成了一本书《智能之门》,讲神经网络基础知识的。
一年多后老板 C 回美国了,木头找机会又转到了研究院所属的一个小的工程团队,这个团队包括老板在内只有 6 个人。
但是很快发现,这 5 个员工每个人参与的项目都不同,5 个人 5 个项目,这就根本不是一个团队的样子。半年内,有两个人辞职离开了,但是并没有引起木头的警觉,只是单纯地认为这是他们由于个人原因而辞职。于是,木头尽心尽力地帮助老板招聘新员工,三个月后,终于招进来两个新同事。而且,经过木头的努力,终于说服老板不要把项目搞得太分散,团队小,集中力量打歼灭战才是正确的做法,最终只留了两个项目,一个是量化交易的工程化,一个是强化学习平台的搭建。
@@ -39,21 +45,23 @@ A 人很好,总会安慰木头说“下次估计希望很大”,但下次 B
这种人越多,团队就越松散。老板也不那么给力,开始还和大家一起吃饭,后来可能觉得掉价儿,也就吃独食了。而且,老板的一些观点也让木头感觉很奇怪,比如说到工作成绩,老板说:“你得让别人说你好才是真的好,咱们自己不能说自己好。” 这是多么奇怪的逻辑!自己不说自己好,指望别人替你说,别人哪里有那多么闲工夫来帮你说话?当老板的不为自己的团队成员争取利益,怎么还能指望大家为团队利益着想呢?
老板在财年结束时并没有帮助木头 promotion,这让木头很伤心,回想起带着兄弟们努力做量化交易工程的日日夜夜,每个工作日的早晨股市开盘前都要看推理系统有没有正常运行,很多时候周末还在加班回答用户的问题和解决一些历史遗留问题(因为涉及到上亿资金的投资决策,用户的要求往往非常苛刻,否则就可能砸了自己的饭碗),感觉投入和回报不成正比。
老板在财年结束时并没有帮助木头 promotion,这让木头很伤心,回想起带着兄弟们努力做量化交易工程的日日夜夜,每周一的早晨股市开盘前都要看推理系统有没有正常运行,很多时候周末还在加班回答用户的问题和解决一些历史遗留问题(因为涉及到上亿资金的投资决策,用户的要求往往非常苛刻,否则就可能砸了自己的饭碗),感觉投入和回报不成正比。
木头和老板谈了一次,老板说:“研究员对量化交易工程项目的印象就是:工程师们只做了一些修修补补的工作。” 木头顿时无语,再一次充分认识到了研究员文化和工程师文化的不同,工程师的工作成绩怎么可能让研究员来评头论足,而你作为老板每周参加两次内部例会、每两周参加一次外部例会,却没有自己的一个正确的评判吗?
这种团队不继续待下去也罢!
【最佳实践】这不能称之为团队,只是一个小组而已。遇到这种团队时,应该尽快离开。老板不给力,团队成员各自为战,项目上也是处于给人帮忙的地位。你自己再努力也没有用。在研究院学习的 AI 知识是一笔宝贵的财富,但是很少有人可以有这种机会,在繁忙的工作中有专门的时间可以学习,就好比在一座高山上砍柴时发现了一本武功秘籍。
#### 在工程院的团队
#### 4. 在工程院的团队
木头闪电般地 transfer 到了工程院的一个二十多人的团队。入职当天,新老板给挨个儿介绍了一下新同事,但是根本记不住那么多人名儿啊!中午 12:30 大家一起吃饭,是最放松的时候,木头可以借机听听大家感兴趣的话题,互相间的称呼是什么,都有什么业余爱好和习惯,少说多听。
木头闪电般地 transfer 到了工程院的一个二十多人的团队。入职当天,新老板给挨个儿介绍了一下新同事,但是根本记不住那么多人名儿啊!中午 12:30 大家一起吃饭,是最放松的时候,木头可以借机听听大家感兴趣的话题,互相间的称呼是什么,都有什么业余爱好和习惯,少说多听。
通过一段时间的接触,木头感觉像是回到了家(因为 8 年前木头就是从工程院出去的),浓浓的工程师文化很令人舒服。木头给大家讲强化学习基础知识,给大家弹琴唱歌,休息时和几个人一起打台球,很快就融入了团队。
在一个项目中遇到 F 哥,他以前也是 MSRA 的 RSDE,后来出去到外面的公司任职,因为外面的公司的薪水较高,等他回来时就拿到了 Principle SDE 的 offer。F 哥人很善良,乐于助人,所以木头和他还很说得来。在团队中,F 哥也不是很爱说话,吃饭总是最后一个才吃完。但是 F 哥不是很灵活,比较固执,遇到不感兴趣的东西就不喜欢去研究,这让老板很失望。很快,半年后 F 哥就待不下去了,Performance Review 的分数不高,他也不愿意继续混下去看别人脸色过日子,所以就又离开了微软。
在一个项目中遇到 F 哥,他以前也是研究院的 RSDE,后来出去到外面的公司任职,因为外面的公司的薪水较高,等他回来时就拿到了 Principle SDE 的 offer。F 哥人很善良,乐于助人,所以木头和他还很说得来。在团队中,F 哥也不是很爱说话,吃饭总是最后一个才吃完。但是 F 哥不是很灵活,比较固执,遇到不感兴趣的东西就不喜欢去研究,这让老板很失望。很快,半年后 F 哥就待不下去了,Performance Review 的分数不高,他也不愿意继续混下去看别人脸色过日子,所以就又离开了微软。
#### 小结
【最佳实践】在外面闯荡了一圈,还是要回到最适合自己的地方。F 哥在研究院的习惯没有改(凭兴趣干活),那么在工程院就呆不下去。对于木头来说,干什么都可以,对得起工资就行。
#### 5. 小结
- 上面发生的这些并不是微软的主旋律,只是木头偶遇的一些小事情。
@@ -65,7 +73,7 @@ A 人很好,总会安慰木头说“下次估计希望很大”,但下次 B
- 在工程院团队,回到了工程师文化氛围,木头会尽职尽责地完成老板交给的任务,有机会的话会帮助别人,有余力的话会探索一些新的领域。
- 经过了这 4 年多的辗转,木头的积累又回到了零,在新的团队中必须重新积累才有可能获得 promotion。但是一个朋友告诉木头:“看上弯曲的路也许能通向更远的地方。” 确实,木头在 MSRA 自学了很多 ML/AI 相关的知识,对以后的 career path 有很大的帮助。
- 经过了这 4 年多的辗转,木头的积累又回到了零,在新的团队中必须重新积累才有可能获得 promotion。但是一个朋友告诉木头:“看上弯曲的路也许能通向更远的地方。” 确实,木头在 研究院 自学了很多 ML/AI 相关的知识,对以后的 career path 有很大的帮助。
- 如何决定应该离开一个团队?有三点可以参考:
1. 是否有成就感?
@@ -81,27 +89,27 @@ A 人很好,总会安慰木头说“下次估计希望很大”,但下次 B
图 4.4.1 个人与团队的关系
马克思说:“人是最名副其实的社会动物”。团队就是社会的一个缩影,所以马斯洛的需求层次论在这里依然具有指导意义。
马克思说:“人是最名副其实的社会动物”。团队就是社会的一个缩影,所以马斯洛的需求层次论在这里依然具有指导意义,表 4.4.1 就标记出了个人行为守则在马斯洛需求层次论中的作用
表 4.4.1 个人在团队中需要
表 4.4.1 个人在团队中行为守则与需要
||生存的需要|安全的需要|归属的需要|尊重的需要|自我实现的需要|
|-|-|-|-|-|-|
|恪守己任|$\surd$||||$\surd$|
|遵守规则||$\surd$|||
|恪守己任|$\surd$|$\surd$||||
|遵守规则|$\surd$|$\surd$|$\surd$||
|善于沟通||$\surd$|$\surd$|||
|集体利益|$\surd$|$\surd$|$\surd$|||
|集体利益||$\surd$|$\surd$|$\surd$||
|献计献策|||$\surd$|$\surd$||
|帮助他人||||$\surd$|$\surd$|
#### 恪守己任(Be Responsible
#### 1. 恪守己任(Be Responsible
在社会中,人们需要食物、水分、空气、睡眠等才能生存下去;在团队中,基本的生存法则就是恪守己任,保质保量完成领导或团队指派的任务,在别人眼里获得真实的存在价值或虚幻的存在感,而在自己心中则满足自我实现的需要。
不能像 T 哥那样挑肥拣瘦,领导最不喜欢那样的成员。因为这个任务如果你不去完成,就要找另外一个人去完成,为了不让你闲着,还要另外给你再找一个新任务。这会拉低整个团队的效率。
不能像 F 哥那样挑肥拣瘦,领导最不喜欢那样的成员。因为这个任务如果你不去完成,就要找另外一个人去完成,为了不让你闲着,还要另外给你再找一个新任务。这会拉低整个团队的效率。
#### 遵守规则(Follow the Rule
#### 2. 遵守规则(Follow the Rule
自己生存没有问题后,人们需要稳定、安全、受到保护、有秩序的环境,能免除恐惧和焦虑等;在团队中,就是避免你与大家格格不入因而被“攻击”,所以要遵守(团队)规则。
@@ -122,7 +130,7 @@ A 人很好,总会安慰木头说“下次估计希望很大”,但下次 B
遵守规则,就不会给自己和别人带来麻烦,从而带来持续的安定团结,尽管这种安定团结有可能是表面上的。
像 L 博士那种性格,不愿融入团队并不会给团队带来损害,但是时间久了没人原意和他说话,在关键时刻也不会替他说话,这会给他自己带来损害。
#### 善于沟通(Communication Skill
#### 3. 善于沟通(Communication Skill
安全没有问题后,要寻求与其他人建立感情的联系或关系:结交朋友、追求爱情等等;在团队中,就是需要有一定的沟通技巧。
@@ -130,10 +138,10 @@ A 人很好,总会安慰木头说“下次估计希望很大”,但下次 B
上面提到的女生 J,给别人的感觉就是她关心自己的宠物比团队成员更多,和团队成员包括和老板沟通时,都还饱含学生时代的青涩味道。不融入团队,就学不会沟通技巧;不善于与人沟通,就只能和宠物说话了。
木头在 MSRA 那个小团队时,可以招三名实习生。最开始时,老板还要为实习生面试把关,和木头 argue “这个实习生的学校不是很 top 呀” 等等。英雄不问出处,木头自己有自己的评判标准。如果是一个比较简单的工作,找一个清华北大的博士生来,人家还不乐意干呢;如果是一个比较难的工作,清华北大的学生缺乏动手能力的话也未必能完成。后来,木头把这些实习生所在的学校为这些实习生写的“优秀毕业生”的文章发到群里,老板就改口风了:“以后实习生的面试你全权负责!”
木头在 研究院 那个小团队时,可以招三名实习生。最开始时,老板还要为实习生面试把关,和木头 argue “这个实习生的学校不是很 top 呀” 等等。英雄不问出处,木头自己有自己的评判标准。如果是一个比较简单的工作,找一个清华北大的博士生来,人家还不乐意干呢;如果是一个比较难的工作,清华北大的学生缺乏动手能力的话也未必能完成。后来,木头把这些实习生所在的学校为这些实习生写的“优秀毕业生”的文章发到群里,老板就改口风了:“以后实习生的面试你全权负责!”
#### 集体利益(Team First
#### 4. 集体利益(Team First
既然是团队的一份子,应该多为团队着想。在某些情况下个人利益要服从于集体利益的。
@@ -142,13 +150,13 @@ A 人很好,总会安慰木头说“下次估计希望很大”,但下次 B
当年包括木头的那 20 多号人去做手机 Edge 浏览器,就是为了公司的大利益而牺牲了 Windows China 团队的小利益;而木头去虽然不喜欢测试工作(繁琐、没有技术含量、不引人注目),但还是为了保证产品质量而牺牲了自己的利益。最后产品成功,功劳全归到开发,苦劳全归测试。
#### 献计献策(Contribute Ideas
#### 5. 献计献策(Contribute Ideas
初来乍到一个团队,有很多情况不了解,你肯定插不上话,最好也不要插话,避免闹笑话。当熟悉了情况之后,你就可以在自己有知识存储的领域或者有熟练技能的领域发表意见了,为团队分享自己的想法和建议。可以带来的好处是:
- 你的建议有价值,别人会对你刮目相看,你会得到更多的尊重,以后有类似的事情还会咨询你。
- 相关的人会把你当成“自己人”或是“能人”,拉近你们的关系,获得归属感。
#### 帮助他人(Help Others
#### 6. 帮助他人(Help Others
如果献计献策只是利用已有的知识和技能口头上帮助他人,那么这里就需要真的花时间、花精力来动手帮助他人了,带来的好处是巨大的:
- 帮忙成功了,别人会对你尊重有加;即使不成功,也会心存感激。
@@ -1,13 +1,105 @@
## 4.5 团队之间的合作
在《卓有成效的敏捷》一书中,作者专门讲了关于分布式团队的问题,他的基本观点是:分布式团队肯定会带来一些问题,但是在跨国公司中或者在一个大公司中是不可避免的。作者也提出了一些针对性的建议。
笔者在微软工作多年,和外国团队打交道是家常便饭,所以也总结了一些观点和做法供读者参考。当然,这同样适用于都在国内的两个跨地区团队的合作。
<img src="img/Slide13.SVG"/>
图 4.5.1 团队之间的合作
### 4.5.1 建立通信
### 4.5.1 争脸不争嘴,建立通信
### 4.5.2 建立互信
我们假设团队 A 已经在一个项目上工作了一段时间了,此时团队 B 主动想和 A 合作,而且 A 也需要额外的力量来帮助项目快速发展。此时 B 要做的事情是:**先要和 A 建立通信**。
### 4.5.3 建立自信
建立第一印象非常重要,所以当 B 向 A 介绍自己时,需要一些基本的信息:
### 4.5.4 建立威信
- 我们是谁?
这并不是要把团队成员的名字都列出来,而是把自己的组织结构说清楚,隶属于谁,内部结构如何,主要领导是谁,等等。
- 我们团队有多少人?
包括开发人员和 PM 的人数,以及一些额外的资源,比如合同工(vendor)。
- 我们在哪个地理位置工作?
这在跨国公司中很重要。北京团队与苏州团队的合作是很容易建立的,但是北京团队与西雅图团队的合作就比较难一些,因为时区、语言、文化的不同。
- 我们都有哪些项目经验?
这一点在个人面试时很重要,但是在团队合作时不是非常重要,因为一个团队的能力是不受限的。比如,木头的所在的团队以前一直做操作系统相关的工作,忽然有一天上级要求全体转到手机开发上,这对于大家来说其实是一件好事,可以多学一种开发技能。而且由于团队成员的能力普遍较高,学习能力强,这种转型的时间不是很长。
- 我们可以投入的力量是多少?
不能说我们有 20 个人,但是只有 2 个人空闲着可以考虑参与其它项目。如果要参与的话,至少投入 50% 以上的资源才算做有诚意。或者说在未来的一个月内可以投入 10%,三个月内可以投入 50%,半年后可以投入 80% 等等,也是可以接受的。
当然,通信是双向的,B 介绍了自己,A 也应该考虑是否和 B 合作,有哪些任务可以分给 B 去独立的完成。也许可以先分出一些不那么重要的任务,看看团队 B 的能力,然后再决定时候继续合作。
【最佳实践】这个阶段先要保证多“露脸”,让对方知道有你们这个团队的存在,开会的时候提几个很容易回答的问题,别人说什么都不要顶嘴,所以叫做**争脸不争嘴**。
### 4.5.2 争名不争利,建立互信
团队 A 和团队 B 达成合作后,团队 B 就应该放低身价,先用各种方式来建立对方的信任关系。这就好比两个人做生意,你能不能在第一次合作时按时保质完成合同,决定了以后的进一步的合作关系。缺乏诚信,每次只想捞一笔就跑的人,不可能做大做强。
那么如何建立团队之间的信任呢?
- 按时沟通
团队 B 得到了团队 A 分出来的一部分任务后,应该指定专人与对方保持联系,这个人叫做联络员(Contact),一般来说由 PM 或者 Dev Manager 担任。团队 B 的联络员主要职责是搞清楚团队 A 的架构,知道遇到什么问题时该问谁,当需要比较详细的技术细节沟通时,可以拉上开发人员一起讨论。
团队 A 一般也会指定一个联络员,解答团队 B 的问题。
这就好比系统内两台服务器之间的“心跳”,有事儿没事儿打个招呼也是好的。让笔者好奇的是韩朝之间的热线,每个工作日的上午 9 点和下午 5 点定时通话,相信双方一定是用韩语聊,但是不知道都聊什么。
- 信守承诺
答应的事一定要按时保质完成,尤其是团队 B,更要注意这一点。
假设有个任务是团队 A 分过来的,要求一个月搞定。B 这边最开始的评估不准确,两个人半个月进展不大。此时 B 不应有任何犹豫和借口,应该加大投入力量,尽力争取按时完成。
如果预期实在是完不成,怎么办?B 应该至少提前一周向 A 通报。实际上,B 应该每周和 A 进行一次进度通报,遇到任何困难时,不要顾及面子,直截了当地向 A 咨询。相比之下,最后不能按时完成任务会更丢人。
笔者曾经在换了一个团队之后,做过一个前沿性质的小项目,技术含量较高,最后总算完成了。当时笔者的老板还不是很了解笔者,通过这个项目,老板说:很多人在项目的最后阶段都会掉链子,你没有掉链子,很不错。就此建立了良好的信任关系。
- 降低身段
对于任务不要挑肥拣瘦。对于团队 A 来说,更多的情况下当然是把那些费力不讨好的任务分给团队 B,美其名曰“是个相对比较独立的任务”。团队 B 当然也不是傻子,但是要装成傻子,拿出“吃亏是福”的心态来。因为是团队 A 建立的项目,是先入者,也是规则制定者,团队 B 要认清自己的地位,遵守 A 指定的规则,哪怕它是不合理的规则,以双方共同的利益为首要考虑目标。
【最佳实践】自己的团队有了什么成绩当然要公开,是所谓**争名**,因为这是既成事实,谁也抹杀不掉;但是不居功自傲,保持谦虚,不以此为理由去“抢肥肉”吃,是所谓**不争利**。
### 4.5.3 争地不争权,建立自信
在这第三阶段中,双方已经相互信任了,做为后来者的团队 B,应该考虑进一步的发展,不能总以给别人打工的姿态出现。谁也不比谁差多少,需要建立自己团队的自信。
- 主动出击
当自己的团队有更多的闲置资源时,要主动提出要求,承担更多的工作,而不是满足于自己当前所能掌控的那个小领域。
木头的团队是与美国团队合作工作的。木头的老板经常提醒团队成员,在完成手头工作后,看看能不能参与更多的工作内容,一方面是了解更多的东西,另一方面是寻找机会:美国团队不愿意做的事,我们可以做;或者是他们还没有想到的事,我们也可以自己做起来。
- 抢占地盘
一个是指的还未开始的新任务,团队 B 应该主动承担;另外一个是指一些需要维护的旧模块,团队 B 也可以拿过来维护,通常团队 A 会在此时把维护工作交给团队 B,以便轻装上阵夺取更大的胜利。团队 B 不要拒绝,这是抢占地盘的最佳时机,这些东西积累越来愈多时,大家都会发现这个项目已经离不开团队 B 了,因为有些模块只有团队 B 的人了解细节了。
- 出谋划策
无论是在开会时,还是在日常交流中,遇到一些技术问题时,可以在经过慎重思考后主动出谋划策,甚至是自己先私下解决这个问题,然后把解决方案拿出来给大家讲解。通过这种方式,能够证明在这个项目中,团队 B 已经和团队 A 一样具有发言权了,就可以建立自己团队的自信。但要切记团队中的任何一个人犯错,都会影响整个团队的信誉。
【最佳实践】**争地**即承担更多的工作内容,抢地盘儿这事儿可以悄悄地进行;不需要非得有什么话语权,讨论问题是说出自己的理由,对方不听就算了,就是**不争权**,一个产品的实现可以有很多种方法,不采用自己的方法其实也无所谓。
### 4.5.4 争里不争外,建立威信
在这第四阶段时,团队 B 在项目中所占的比重有半壁江山了,已经有相当程度的话语权了,这是前面三个阶段艰苦努力的结果。但是此时仍然不能觉得自己翅膀硬了可以单飞了,万一哪里不小心得罪了团队 A,对整个项目还是不利。此时在合作中应该建立起本方的威信。
- 以勤助威
不管到了任何阶段,取得了何种成就,都不能偷懒,始终保持适度的工作强度。松散的团队可能会口头上对那些勤奋的团队有些微词,但是从心里都是很佩服的,这就是威信的来源。
读者可能会观察到,在大自然中的动物都非常的勤快,因为它们只要一懒下来,第二天就会饿肚子。保持一种生存的压力,在任何时候都是有好处的,最明显的是你根本不用考虑什么减肥,因为大脑思考的能量消耗是非常大的,一个勤于思考的人不容易胖起来。
- 以和助威
和为贵。团队之间的合作,难免会有些插曲。中国文化讲究谦虚低调,专家作报告时一般会说“本人能力有限,有不妥之处,请大家海涵”。西方人听了就皱眉头了:既然自己知道有不妥之处,为什么还要讲?在技术领域中的人,中西方差别不大,但是在非技术领域,老外非常自信,甚至自大。比如,和一个老外的 developer 很容易谈话,但是和一个老外的 designer 或 PM 就不那么容易达成一致。
此时,我们要做的是和而不同,有自己的想法就直接说出来,但不要和对方争吵。另外,你用英语交流,不是自己的母语,也说不过对方。最后就明确告知对方:可以按照你说的做,但是我保留意见。那么对方在下次可能也会改变态度。
- 以情助威
和其它团队的沟通,并不是现定于工作上的,也可以分享一些工作之外的事情,拉近双方的距离。比如,木头的乐队演出录像,就会通过内部的 Teams 分享给老外的团队,他们都很感兴趣,虽然听不懂中文歌,但是吉他、贝斯、鼓都是认识的。这在另一方面也展示了本方的才能,让对方佩服。
- 以能助威
其实最根本的,就是提高本方团队的能力,具体体现在:按时完成本方负责的任务、提交高质量的代码而不会导致系统故障、能及时地解决软件运行中出现的问题、有理有据的讨论、承担更多的工作、提供有远见的方向性建设意见,等等。本身的能力强,自然对方会尊重你。
【最佳实践】里子和面子,哪个更重要?一般人会两者都要,但是如果一定要面子,很可能走错了方向。所以我们强调**争里不争外**,有些事情做错了就大大方方承认,然后你就会体会到天地忽然宽广了感觉,就应了那句话:退一步《海阔天空》,忍一时《光辉岁月》。内在的强大,才是真正的强大,才能够建立威信,得到尊重。
@@ -4,36 +4,36 @@
在任何公司里都会有实习生的存在,从“阳光”的一面说:一方面给公司做一个人才储备,另一方面给在校学生一个社会实践的机会。从“阴暗”的一面说:实习生工资低,公司投入的不大,有些技术含量不高的工作可以在导师的指导下由实习生承担。
MSRA,通常一个导师会带 2~3 个实习生,承担数据处理、试验准备、模型训练、试验结果验证及总结、论文初稿等工作。所以导师与实习生构成了一个比较小的团队,在这样众多的小团队里也会发生一些故事。
研究院,通常一个导师会带 2~3 个实习生,承担数据处理、试验准备、模型训练、试验结果验证及总结、论文初稿等工作。所以导师与实习生构成了一个比较小的团队,在这样众多的小团队里也会发生一些故事。
<img src="img/Slide14.SVG"/>
#### 给定目标和范围
#### 1. 给定目标和范围
木头曾经带过一个实习生小 S,他在某个视频网站上给大家讲高数中的学习难点,给木头留下很深刻的印象,觉得他思路清晰、口齿伶俐、乐于助人,所以就招聘了他。入职后给他分配第一项任务:“小 S,这里有几篇论文,都是关于古典音乐作曲的 AI 模型的,你都看一看,然后挑出一篇来重点研究。” 小 S 很痛快地答应了。
#### 迷失方向,找不到重点
#### 2. 迷失方向,找不到重点
过了三天,木头询问进度,小 S 答道:“老师,这些论文我都看了看,感觉参考价值不是很大啊!” 木头觉得可能是实习生无法分辨出重点,笑了笑说:“那你发现更有参考价值的论文了吗?”“没有啊。”(注意,实习生说话都习惯尾缀“啊”字)。木头指了一下其中一篇论文说:“那你读一下这篇论文,把它所描述的模型复现一下吧。” 小 S 很痛快地答应了。
#### 缺乏经验,没有工作方法
#### 3. 缺乏经验,没有工作方法
过了三天,木头询问进度,小 S 答道:“老师,论文中有含糊不清的描述,而且我也没有试验环境,所以可能复现不了。” 木头想了想,觉得刚入职的实习生可能是因为经验不足,也不能勉强,所以说:“那你把试验数据准备一下吧?” 小 S 很痛快地答应了。
#### 偷闲躲静,总想找捷径
#### 4. 偷闲躲静,总想找捷径
过了两天,小 S 说:“老师,那个数据我觉得很乱啊,可能需要花费很多时间写代码才能整理出来啊。我想找找网上有没有人公开可供下载的已经准备好的数据。” 木头想了想,觉得也未尝不可,就说:“行吧,那你去找一找。” 小 S 很痛快地答应了。
#### 异想天开,但眼高手低
#### 5. 异想天开,但眼高手低
过了两天,木头询问进度,小 S 说:“老师,没有找到可以下载的数据啊,我觉得这篇论文应该是没有什么名气,所以没有其他人做类似的试验啊。” 木头轻轻皱了皱眉头,问到:“那你觉得应该怎么做呢?” 小 S 说:“我们可以自己搭建几个模型多做试验做比较啊,我觉得会比复现别人的模型快一些。” 木头说:“行...吧,那你尝试着自己搭模型试试。” 小 S 很痛快地答应了。
#### 技术能力有限,也不想学习
#### 6. 技术能力有限,也不想学习
过了一周,木头问进度,小 S 面带难色地说:“老师,搭模型我不还不太会啊,我实习期只有六个月,等学习完搭建模型了也结束实习了,您能不能给我分配一个别的任务啊?” 木头轻轻叹了口气,说:“嗯,那你帮助另外一个实习生小 X 处理数据吧?” 小 S 很痛快地答应了。
#### 缺乏一般的职业习惯,没有基本的工作纪律
#### 7. 缺乏一般的职业习惯,没有基本的工作纪律
有过了几天,木头问小 X:“小 S 有帮助你处理数据吗?” 小 X 说:“小 S 最近经常下午来得很晚,不知道在忙些什么,然后很快就离开办公室回学校了。”
File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 762 KiB

After

Width:  |  Height:  |  Size: 425 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 180 KiB

After

Width:  |  Height:  |  Size: 320 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 43 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 30 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 62 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 58 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 59 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 62 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 72 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 65 KiB

@@ -1,18 +1,10 @@
<img src="img/Slide1.JPG"/>
<img src="img/Slide1.SVG"/>
注意我们使用了“流程(Procedure)”,而非“过程(Process)”,强调的对是软件工程的过程中的各个环节的事无巨细的掌控和对关键点的监督。而过程是一种点到为止的叙述,最后注重的是结果
本章仍然是先用一个开发流程进化的故事,来告诉读者一个成熟的软件产品的“履历”。然后介绍了软件开发的各个阶段的任务与产出。接下来详细讲述了不同类型的软件项目的流程,包括小型软件项目、中大型软件项目、研究型项目等,并介绍了著名的敏捷开发流程,以笔者不同的视角对其进行刨析
- 通过对书本知识(比如本书)的学习,读者可以了解到软件工程的**过程**;
- 而**流程**必须通过动手实践才能得到切身体会。
比如那个家喻户晓的笑话:“如何把大象放到冰箱里?” 答曰:“1. 把冰箱门打开;2. 把大象牵进去;3. 把冰箱门关上。” 这其实就是一种对**过程**的描述,它可以通过忽略具体细节而混淆视听。
还有一个例子,就是木头如何鼓励新手上台表演:“你就背着吉他,眼睛不用看台下以免紧张,然后弹和弦 1645,1645,1645......,鞠躬下台,多简单的**过程**!” 但实际上,吉他手上台表演,要考虑站位、站姿是否符合舞台要求,吉他连接到调音台后音量、音色的调节,和弦进行 1645 要克服大横按的一些操作难点,还要听鼓的节奏避免错拍,还要根据歌手的情绪来调节扫弦的力度,等等。这一系列**流程**能顺利走下来都是必须经过长期练习才能做到。
<img src="img/Slide2.JPG"/>
<img src="img/Slide2.SVG"/>
@@ -21,6 +13,7 @@
- The Chicken and the Pig, Wiki Pedia, https://en.wikipedia.org/wiki/The_Chicken_and_the_Pig
- 《构建之法》,邹欣,人民邮电出版社
- RASCI Responsibility Matrix, https://managementmania.com/en/rasci-responsibility-matrix
- 《卓有成效的敏捷》,史蒂夫·麦克康乃尔,人民邮电出版社
- 什么是MVP? https://tsh.io/blog/mvp-app-and-the-other-validation-methods/
@@ -1,4 +1,4 @@
## 5.1 开发流程进化的故事
## 5.1 开发流程进化
现代软件工程的开发流程已经非常成熟了,但是读者可能会产生的问题是:这些阶段真的都有必要存在吗?会不会很浪费时间?
@@ -6,11 +6,13 @@
从下面的故事中,读者可以感同身受,从小到大逐步领会到经典划分方法的必要性。
<img src="img/Slide3.JPG"/>
### 5.1.1 开发流程进化的故事
<img src="img/Slide3.SVG"/>
图 5.1.1 软件工程中的开发流程的进化过程
### 5.1.1 开发-修改
#### 1. 开发-修改
给自己写软件。Build for Self。
@@ -20,7 +22,7 @@
在软件工程还没有出现之前,大家都是处于“开发-修改”的状态,当时的软件也不复杂,代码量不大,所以还是可行的。很多年前,做一个“个人开发者”很时髦,因为很多传统领域都需要软件,那时随便写个软件都能挣钱,木头也确实干过“私活儿”,用挣到的“外快”买了自己的电脑(然后开始打游戏)。
### 5.1.2 需求-开发-修改
#### 2. 需求-开发-修改
给朋友写软件。Build for Friend。
@@ -30,7 +32,7 @@
如果给公司内部做软件或者给团队内部做一个工具,基本上就是这种形式。不太在意什么性能、易用性等等,所以在即使是在微软,内部使用的一些工具类软件也都特别难用。
### 5.1.3 需求-开发-测试-共享
#### 3. 需求-开发-测试-共享
免费给更多的人写软件。Build for Relationship。
@@ -44,7 +46,7 @@
到了这一阶段,出现了多人合作开发的情况,并且出现了测试环节,是一种团队流程的萌芽。由于是免费的,所以没法要求开发者可以提供更多的维护和技术支持,现在很多 GitHub 上的开源项目就是如此,使用的时候需要特别小心,遇到 bug 得自己去解决,不要指望开源者帮你。
### 5.1.4 分析-设计-开发-测试-分发
#### 4. 分析-设计-开发-测试-分发
写复杂的商业软件。Build for Business。
@@ -62,7 +64,7 @@
到了这一步,已经正式进入团队开发流程了,形成了传统(经典)的阶段划分方法。很多初创团队或小的软件公司都是处于这种阶段,他们有自己的技术实力和积累,但是需要紧密地结合市场需求才能赚钱。
### 5.1.5 分析-原型-设计-开发-测试-部署
#### 5. 分析-原型-设计-开发-测试-部署
写商业化的网络服务软件。Build for Service。
@@ -74,7 +76,7 @@
这一步已经用“私有云”的方式来代替传统软件了,好处就是上面所说的“更新快、免分发、用户广、易收费”等。软件公司到了一定规模,就可以用这种方式赚钱了,当然还可以把故事讲得大一些,以便得到风险投资。
### 5.1.6 分析-原型-设计-开发-测试-部署-运维
#### 6. 分析-原型-设计-开发-测试-部署-运维
写可控的商业化服务软件。Build for Life。
@@ -88,7 +90,7 @@
有了这些基本的运维手段后,系统变得越发的可控,工程师们的日子都好过了些。在工作之余,也可以一起打打台球儿、玩玩儿乐队了,做到 Work Life Balance。一个拥有上百人的中等规模的软件公司可以达到这个程度。
### 5.1.7 计划-分析-原型-设计-开发-测试-部署-运维
#### 7. 计划-分析-原型-设计-开发-测试-部署-运维
写可持续的商业化服务软件。Build for Future.
@@ -98,4 +100,42 @@
在这一阶段中,已经进入了自己控制产品方向和开发节奏的良性**循环**,是软件工程的最高级阶段,像微软的 Windows、Office、Azure 等产品都是如此。但是针对不同的公司,或不同规模/性质的软件产品,这个阶段划分还可以进一步细化,我们在“发布与维护”一章中再讨论。
读者可以初步体会到,软件工程不是一个单向的行为,而是像车轮一样向前循环滚动进行的。关于循环流程我们在 5.5 节中再讨论
读者可以初步体会到,软件工程不是一个单向的行为,而是像车轮一样向前循环滚动(迭代)进行的。
### 5.1.2 迭代式开发模式
每个成熟的产品都是经过不断的迭代,才慢慢变得成熟的,正所谓“罗马不是一天建成的,胖子不是一天吃出来的”。
- 大多数人恐怕没有见过 Windows 3.0 以下的版本是什么样子,当时大家都觉得它的窗口界面好神奇,可是与现在的 Windows 11 相比,简直就是儿童玩具。
- Office 办公套件也是如此,最开始只有 Word,后来加入了 Excel,到现在已经改名为 Microsoft 365 了,家族里 Word, Excel, PowerPoint, OneNote, Publisher, Access, Outlook, Exchange, Bookings, Teams, SharePoint, Yammer, Viva, OneDrive, Stream, Sway, Forms, Visio, Planner, Power Apps 等 20 多个成员。
总结起来,这些产品的开发模式/流程不外乎图 5.1.2 所示。
<img src="img/Slide4.SVG"/>
图 5.1.2 迭代式开发模式
1. 项目计划,指的是商业计划。
2. 需求分析,第七章中要介绍的部分。
3. 架构设计,第十二章中要介绍的部分。
4. 开发当前版本,包括概要设计、详细设计、开发代码、单元测试、集成测试等等。
5. 发布当前版本,发布测试后的软件。
6. 收集用户反馈,可以在线收集文字意见,也可以通过日志来分析用户行为。
7. 制定改进计划,根据反馈制定下次迭代的工作内容。
......
然后又会回到 “4. 开发当前版本”。
在制定改进计划时,有两种可能回退到到开始阶段:
1. 在一个版本发布之后,收集到了新的用户需求,需要回到需求分析阶段。
2. 设计出了一个绝妙的新功能,但是发现现有的框架不支持,需要修改架构设计。
这种改进都是增量式的,很少有全盘推翻以前的工作重新来过的情况发生,总会保留一部分稳定的代码,而增加一部分新功能代码。但是随着迭代次数的增加,旧的代码很有可能被重构没了。
在任意一个节点上,都有可能退出迭代,具体的条件在《构建之法》中介绍过,比如:
- 甲方预测前景不乐观,不再支持本项目。
- 乙方的开发团队由于某种原因解散了。
- 用户还没招募起来,忽然有个竞争产品出现。
- 整个行业不景气,生态系统系统建设困难。
- 监管机构或政府强制该产品下架。
@@ -1,12 +1,42 @@
## 5.2 阶段任务的投入与产出
从 4.1 节的故事中,我们最终得到了最理想的阶段划分方法,这种方法可以满足绝大多数软件工程的需要。但是,有可能给读者留下一个误区:“计划结束后做需求分析,需求分析结束后做原型开发,原型开发结束后做系统设计......” 但其实没有一个交割点来绝对地分开前后两个阶段,甚至在某个时间段内,有多于 2 个阶段任务的重叠情况。见图 5.2.1。
## 5.2 软件开发过程说明
<img src="img/Slide4.JPG"/>
### 5.2.1 流程与过程
图 5.2.1 阶段任务投入密度曲线
请注意我们本章的标题使用了“流程”,但是本节的标题是“过程”。前者强调的对是软件工程的过程中的各个环节的事无巨细的掌控和对关键点的监督。而后者是一种点到为止的叙述,最后注重的是结果。
投入密度:关于投入的劳动资源随着时间而形成的密度曲线,越高表示此时刻共同工作的人越多或者劳动强度越大。可以用概率密度曲线做类比理解
- 通过对书本知识(比如本书)的学习,读者可以了解到软件工程的**过程**
- 而**流程**必须通过动手实践才能得到切身体会,要在实际工作中解决遇到的具体问题。
比如那个家喻户晓的笑话:“如何把大象放到冰箱里?” 答曰:“1. 把冰箱门打开;2. 把大象牵进去;3. 把冰箱门关上。” 这其实就是一种对**过程**的描述,它可以通过忽略具体细节而混淆视听。
还有一个例子,就是木头如何鼓励新手上台表演:“你就背着吉他,眼睛不用看台下以免紧张,然后弹和弦 1645,1645,1645......,鞠躬下台,多简单的**过程**!” 但实际上,吉他手上台表演,要考虑站位、站姿是否符合舞台要求,吉他连接到调音台后音量、音色的调节,和弦进行 1645 要克服大横按的一些操作难点,还要听鼓的节奏避免错拍,还要根据歌手的情绪来调节扫弦的力度,等等。这一系列**流程**能顺利走下来都是必须经过长期练习才能做到。
所以,可以认为过程是比流程更大更粗略的概念。
在英文中的 Procedure 和 Process 也是如此:流程(Procedure)是指关于如何执行构成流程一部分的特定任务的详细说明。过程(Process)是指实现特定目标的一系列事件。那么我们本章的英文标题为什么是 Development Process 呢?
软件开发是指使用计算机程序代码实现软件功能的**过程**,包括软件的总体结构、模块的组成、功能的设计、程序的编译、调试、联调、测试等过程。软件开发通常分为以下 6 个阶段:
1. 商业计划:分析软件开发的目标、需求、成本、风险等,确定软件开发是否可行。
2. 需求分析:详细地分析客户的软件功能需求,制定需求变更计划,保证软件开发过程的顺利进行。
3. 系统设计:根据需求分析结果进行软件设计,涉及到软件设计框架结构、软件系统模块和软件系统的数据库,主要分为总体设计和详细设计两部分。
4. 软件开发:根据软件设计用编程代码实现软件功能。
5. 测试分析:对完成的软件程序进行单元测试、组装测试、系统测试等,检查程序的正确性,客户要求功能的充分性,以确定软件是否满足开发要求,这也是一个发现问题、纠正问题的过程。
6. 运行维护:将完成的软件系统交付给客户,并向客户提供软件安装程序、数据库的数据字典、用户安装手册、用户使用指南等文档,指导客户安装软件及使用技巧。同时提供售后服务,维护软件,或者根据用户的新需求修改应用软件程序,不断满足客户的实际需求。
所以,从上面的描述可以看出,**软件开发既是一个过程,也是一个流程**。该过程中包括对 6 个阶段的一般步骤和规范的说明,每个阶段中有具体的流程描述,包含具体的软件开发活动和实践。流程和过程相辅相成,共同保证了软件开发的质量和效率。
### 5.2.2 阶段任务的投入与产出
从 5.1 节的故事中,我们最终得到了最理想的阶段划分方法,这种方法可以满足绝大多数软件工程的需要。但是,有可能给读者留下一个误区:“计划结束后做需求分析,需求分析结束后做原型开发,原型开发结束后做系统设计......” 但其实没有一个交割点来绝对地分开前后两个阶段,甚至在某个时间段内,有多于 2 个阶段任务的重叠情况。见图 5.2.1。
<img src="img/Slide5.SVG"/>
图 5.2.1 阶段任务资源投入曲线
图 5.2.1 中的图例如下:
- 斜腰三角形
逐步热身,积累想法,到尖顶儿时形成初步文档,后期逐步补充完善。
@@ -23,9 +53,15 @@
- 矩形
熟悉时间极短,立刻全员投入并持续。
红色虚线所覆盖的阴影部分,是项目组所有人员的投入密度
投入率:关于投入的劳动资源随着时间而形成的曲线,越高表示此时刻共同工作的人越多或者劳动强度越大
### 5.2.1 计划
红色虚线所覆盖的阴影部分,是项目组所有人员的投入率,其某一横坐标点上的高度是具体的投入率值。比如,在初期(10%进度内),投入率最高低于 25%,在 80% 进度区间内为 95% 以上。
另外,细心的读者可以发现在图 5.2.1 中,列出了 8 个阶段,而不是上文中的 6 个,这是为什么呢?一是增加了“原型”阶段,这一点经常被忽略;二是增加了“部署”阶段,这在相当于传统软件中的“分发”,相当于现代软件工程中的云端物理部署,需要专门的设计工作支持。
各个阶段的产出在图 5.2.2 中展示。
#### 1. 计划
软件项目计划(Software Project Planning)。
人员:商务人员、项目经理、技术负责人。
@@ -55,7 +91,7 @@
在图 5.2.1 中的第一行,此项任务的投入密度是一个三角形,开始时大家零散地贡献想法,积累到一定程度后开始形成文案,后期逐渐补充完善。
### 5.2.2 分析
#### 2. 分析
即软件需求分析(Requirement Analysis)。
@@ -65,7 +101,7 @@
一个中大型软件系统需要完整的需求调研、需求分析过程,并形成文档并经过共同评审,避免做出来的东西和想要的东西不一致。在初期尽快、尽多地明确需求,在后期可以逐步补充缺失或者不明确的地方,但是不能对已经开始的系统设计产生大的影响。详见第 3 部分。
### 5.2.3 原型
#### 3. 原型
即原型系统设计及确认(Prototyping)。
@@ -75,7 +111,7 @@
力争在较短时间内发布原型,包括设计图或者可执行的软件,并与需求方确认主要流程和关键细节,避免遗漏或误解。该原型系统可以浏览,甚至可以交互(mock up,随机的输入和预定的输出)。系统设计师要给出概念验证原型和技术选型建议。详见第 5 部分。
### 5.2.4 设计
#### 4. 设计
即系统分析与架构设计(System Analysis and Architect Design)。
@@ -83,22 +119,23 @@
产出:架构设计文档,视觉/交互设计文档,或概要设计文档。
时间:从原型确认后开始,尽量短,不要超过总时间的 30%。
对于大中型系统,需要架构设计,因为要考虑框架的灵活性、可维护性等。在架构设计文档中要包括 4+1 视图:
- 场景视图
- 逻辑视图
- 运行视图
- 开发视图
- 物理视图
对于大中型系统,需要架构设计,因为要考虑框架的灵活性、可维护性等。在架构设计文档中要包括 6 个视图:
- 应用场景视图
- 逻辑功能视图
- 运行过程视图
- 数据存储视图
- 软件开发视图
- 物理部署视图
任何规模的系统都需要概要设计,详见第 5 部分。有时候概要设计可以放在下一个阶段(开发)。
任何规模的系统都需要概要设计,详见第 5 部分。
<img src="img/Slide5.JPG"/>
<img src="img/Slide6.SVG"/>
图 5.2.2 每个阶段的任务产出
### 5.2.5 开发
#### 5. 开发
即软件编码、单元测试(Coding and UnitTest)
即软件编码、单元测试(Coding and UnitTest
人员:软件开发工程师。
产出:概要设计文档、详细设计文档、可执行代码、单元测试代码。
@@ -113,7 +150,7 @@
- 协助解决部署或运维中的问题;
- 充电积累,参加培训,学习新技术,为新项目做准备。
### 5.2.6 测试
#### 6. 测试
即集成测试(Integrated Testing)、系统测试(System Testing)。
@@ -125,7 +162,7 @@
所谓静态分析、动态分析,是用一些工具对程序的安全性进性分析,避免已知的安全漏洞,比如使用了那些已经发现有安全隐患的第三方库。
### 5.2.7 部署
#### 7. 部署
人员:工程师。
产出:软件配置方案、物理部署方案(包括回滚方案)。
@@ -133,7 +170,7 @@
部署环境包括两个:集成环境、产品环境。首先在集成环境中部署,经过测试成功后再迁移/切换到产品环境。如果能做组件级别的回滚,就可以直接在产品环境中部署局部节点。如果不能,就要准备独立的产品环境,用于一次性的切换。
### 5.2.8 运维
#### 8. 运维
人员:运维人员,项目经理。
产出:日志、图表、报警机制、backlog。
@@ -6,15 +6,15 @@
MARO - Multi-Agent Resource Optimizaiton 多智能体资源优化平台
<img src="img/Slide6.JPG"/>
<img src="img/Slide7.SVG"/>
图 5.3.1 多智能体强化学习平台架构图
#### 项目规模
#### 1. 项目规模
这是一个研究型的项目:一个 dev manager,一个 tech lead,六个 dev2 FTE + 4 Vendor),两个研究员,一个 vendor designer,没有 PM。
#### 项目背景
#### 2. 项目背景
一个跨国海运公司在世界各地的港口都有空的集装箱,需要及时地转运到所需要的港口装载货物。如果用传统的优化算法,每次计算需要花费好几天的时间,而且还不能克服一些临时的因素造成的误差,造成空集装箱没有正确地达到需要的港口。
@@ -24,7 +24,7 @@ MARO - Multi-Agent Resource Optimizaiton 多智能体资源优化平台
但是只有海运这样一个实例的话,是无法泛化的,于是研究员和工程师们又找了共享单车搬运、虚拟机管理、仓储库存管理等几个例子。
#### 资源调整
#### 3. 资源调整
这个平台开发了一年多后,那个 tech lead 要离职,老板让木头接替他。一进来就发现 tech lead 定的例会是每周一、三、五,这就很尴尬:因为周五以后就是周末,如果每个 dev 想在周一的例会上说出点儿什么来,就必须在周末花时间做出进展来。大家轮一圈儿后大概要花 30 分钟,而且那个 tech lead 特能说,每次都讲很多。除此之外,在例会之外他还会经常和每个 dev 单独联系,一讨论就是一个小时,语气很强硬。
@@ -38,7 +38,7 @@ MARO - Multi-Agent Resource Optimizaiton 多智能体资源优化平台
两个月后,领导和木头说,把这个项目交给 3.4 节中提到的女生 E,木头很痛快地答应了,但是每周的两次 sync 还是几个项目一起开,因为人员上有交叉。木头发现女生 E 作为 tech lead,她自己很少写 code,只做 code review。但这与木头无关,索性忽略。
#### 项目分析
#### 4. 项目分析
从用户需求上看:
@@ -70,7 +70,7 @@ MARO - Multi-Agent Resource Optimizaiton 多智能体资源优化平台
- 其实最关键的还是团队的老板,看不清这个项目的未来发展,即不懂技术又不懂管理,被人家画了个饼,却始终吃不到嘴里。
- 还有一点很可笑,所有的文档都是英文的,虽然所有参与人员都是中国人(让木头想起了在美国的墨西哥人为了谋生而开中餐馆)。英文可以有,但是写中文文档不是手到擒来的事情吗?用中文来降低入门的门槛是不是一种合理的考虑呢?
#### 最终结果
#### 5. 最终结果
这个项目开源三年多了,至今虽然还在有人维护,但是处于半死不活的状态,在 GitHub 上只有 660+ 颗星。
@@ -80,27 +80,25 @@ MARO - Multi-Agent Resource Optimizaiton 多智能体资源优化平台
Qlib - Quantitative Library 量化交易平台。命名为一个 Library,意为用户只要调用 API 就可以完成指定的任务。但实际上,它是一个 Framework。也就是说:用户必须按照 Qlib 所规定的流程
<img src="img/Slide7.JPG"/>
<img src="img/Slide8.SVG"/>
图 5.3.2 Qlib 量化交易平台架构图
#### 项目规模
#### 1. 项目规模
这是一个研究型的项目:一个 Dev manager,一个 Tech lead,五个 dev3 FTE + 2 Vendor),三个研究员,一个 PM,两个商务人员,一个外部的长期合作的客户(某基金公司)。
#### 项目背景
#### 2. 项目背景
研究员们研究股票的量化交易很多年了,并建立了一个开源项目:Qlib。可是缺少实盘的机会。某基金公司考察后决定合作,基金公司提供数据,由研究员们提供算法、模型、预测结果,基金公司参考预测结果再结合以往的投资经验来操盘。
#### 要解决的问题
每个交易日,基金公司都要手工上传昨天的交易数据,用微信叫醒熟睡的研究员,研究员去下载交易数据,处理后用模型做预测,然后微信通知基金公司取结果。整个过程基本没有自动化。
每过 60 个交易日,基金公司就要求研究员使用最近的历史数据重新训练模型,在历史数据上比较新旧模型的差异,然后切换模型。这个过程也都是手工完成,很繁复。
木头的任务就是把上述过程工程化、自动化,省去手工操作的麻烦和误操作。
#### 开发流程
#### 3. 开发流程
- 每周二、四,木头会安排组内会议,大家 sync 一下当前进度。
@@ -118,7 +116,7 @@ Qlib - Quantitative Library 量化交易平台。命名为一个 Library,意
- 所有工作都在 Microsoft Azure 上进行,因为客户买了 Azure 的订阅。
#### 项目分析
#### 4. 项目分析
从用户需求上看:
@@ -157,7 +155,7 @@ Qlib - Quantitative Library 量化交易平台。命名为一个 Library,意
- 从与客户的关系看,由于以前研究员们对客户过于“尊重”了,真的把客户当成“上帝”了,搞得 PM 根本拦不住也不敢拦客户的随机要求,这会打乱软件工程活动的正常进行。
#### 最终结果
#### 5. 最终结果
工程师们用了四个月的时间,终于把所有的训练系统、推理系统、模型管理系统做到了自动化,圆满地完成了第一次模型切换,客户很满意。
@@ -165,7 +163,7 @@ Qlib - Quantitative Library 量化交易平台。命名为一个 Library,意
经过上面两个项目,我们总结一下工程师与研究员合作一些研究项目时需要注意的事项。
<img src="img/Slide8.JPG"/>
<img src="img/Slide9.SVG"/>
图 5.3.3 研究员与工程师对软件系统的不同理解
@@ -5,23 +5,23 @@
Torch Nebula,基于 PyTorch 的分布式训练进度的云缓存。
<img src="img/Slide9.JPG"/>
<img src="img/Slide10.SVG"/>
图 5.4.1 Torch Nebula 项目工作原理图
#### 项目规模
#### 1. 项目规模
这是一个小型项目:一个 dev manager,一个 tech lead,四个 dev,没有 PM 和 Designerfirst party(内部)用户。
#### 项目背景
#### 2. 项目背景
在使用 PyTorch 训练大型神经网络模型时,往往使用分布式训练,以数据分布式居多。这种模型往往需要几天甚至几周的时间才能训练完毕,这就需要在训练过程中间歇性地保存当前的训练进度,以备万一机器掉电或框架软件错误造成中断时,可以把最近一次的保存进度加载进来继续训练。
#### 要解决的问题
#### 3. 要解决的问题
由于网络参数过大,调用 torch.save() 函数保存进度写入硬盘往往需要一个多小时,然后才能继续训练,是一种阻塞式的行为。我们的目的就是要提供一个可导入的 python 包,当用户调用这个包提供的 nebula.save() 函数时,可以用异步的方式在后台保存进度,只需要 1 分钟左右的延迟就可以继续训练任务。
#### 关于例会
#### 4. 关于例会
刚一加入这个项目,就发现他们每天上午 11 点都有例会,通过 Teams 开的在线会议,大家 sync 进度,scrum master 是 Tech Lead。他会询问每个人的进度,有问题的话就讨论以下解决办法,或者提醒要注意的关键点。经常进行一些发散性的讨论,造成了一轮 sync 下来会花 40 分钟以上的时间。
@@ -29,7 +29,7 @@ Torch Nebula,基于 PyTorch 的分布式训练进度的云缓存。
但是,每天花 40 分钟有点儿太耽误大家的时间了。另外,项目本身的难度不是很小,所以每天不一定有实质性进展。
#### 开发流程
#### 5. 开发流程
- 木头是以帮忙的身份来加入这个项目的,从零开始建立一个 CI Pipeline,可以把 dev 们提交的 code 在 Pipeline 里自动编译、打包、部署到测试环境,如果测试成功则允许 merge。
@@ -49,7 +49,7 @@ Torch Nebula,基于 PyTorch 的分布式训练进度的云缓存。
- 每两周会总结一下进度,作为一个 Sprint,但是并不严格,因为很多时候计划的任务两周做不完,就会用三周时间。老板也不会催促。
#### 项目分析
#### 6. 项目分析
从用户需求上看:
@@ -68,7 +68,7 @@ Torch Nebula,基于 PyTorch 的分布式训练进度的云缓存。
所以,这是一个比较成功的团队流程。
#### 最终结果
#### 7. 最终结果
当木头离开这个项目组时,已经有不少内部用户使用了 Nebula,反响很好,也得到了领导的夸赞。下一步是想开源这个项目,但不是必须的。
@@ -78,7 +78,7 @@ Torch Nebula,基于 PyTorch 的分布式训练进度的云缓存。
我们以做一个计算器软件为例,说明开发一个小型软件的开发流程的最佳实践(Best Practice)模型,如图 5.4.2 所示。
<img src="img/Slide10.JPG"/>
<img src="img/Slide11.SVG"/>
图 5.4.2 小型软件开发流程的最佳实践
@@ -98,7 +98,7 @@ Torch Nebula,基于 PyTorch 的分布式训练进度的云缓存。
如图 5.4.3 左子图所示。
<img src="img/Slide11.JPG"/>
<img src="img/Slide12.SVG"/>
图 5.4.3 从“能运行”到“结果对”
@@ -140,7 +140,7 @@ Torch Nebula,基于 PyTorch 的分布式训练进度的云缓存。
如图 5.4.4 左子图所示。所以虽然功能都已经实现了,还是没法交给最终用户使用。
<img src="img/Slide12.JPG"/>
<img src="img/Slide13.SVG"/>
图 5.4.4 从“功能全”到“给用户”
@@ -9,7 +9,7 @@
计算机的应用可以追溯到第二次世界大战前,是名副其实的“国家机器”。真正的商业计算机及软件,应该是从上个世纪 50 年代开始的,最初用于构建大型的复杂商业应用,后来发展成为个人计算机,又发展到移动设备。终端设备的变化导致软件的变化,而软件体量、内容、形式上的变化,必然会导致软件开发团队的理念和流程的变化。如图 5.5.1 所示。
<img src="img/Slide13.JPG"/>
<img src="img/Slide14.SVG"/>
图 5.5.1 软件体量和形式的变化
@@ -110,7 +110,7 @@
原文中的 12 条原则是按照一个不规则的顺序列出的,笔者把它们归纳到四大核心价值中,并附加了一些解释,便于大家理解。
<img src="img/Slide14.JPG"/>
<img src="img/Slide15.SVG"/>
图 5.5.2 敏捷宣言及其 12 个原则(分类)
@@ -181,7 +181,7 @@
### 5.5.4 敏捷开发流程
<img src="img/Slide15.JPG"/>
<img src="img/Slide16.SVG"/>
图 5.5.3 敏捷开发流程
@@ -220,7 +220,7 @@
开发人员领到任务后,估算开发时间,填写到任务中。如果任务还是太大(超过 5 天),就继续分解成更小的任务。
<img src="img/Slide16.JPG"/>
<img src="img/Slide17.SVG"/>
图 5.5.4 Backlog 待办事项中的内容项的层次关系
@@ -5,31 +5,31 @@
ONNX Converter。
<img src="img/Slide17.JPG"/>
<img src="img/Slide18.SVG"/>
图 5.6.1 ONNX 技术栈
#### 项目规模
#### 1. 项目规模
这一次的项目个大家伙:ONNX 其实是一个产品,全部的开发人员大概有 200 多人。木头参与的是其中一个子项目 ONNX Converter,算是中等项目吧。一个 dev manager,没有 tech lead10 几个 dev,而且分布在美国东西部、法国、中国等四个办公地点。
#### 项目背景
#### 2. 项目背景
ONNXOpen Neural Network Exchange)开源项目,开放的神经网络模型交换格式。作为框架共用的一种模型交换格式,使用 protobuf 二进制格式来序列化模型,可以提供更好的传输性能我们可能会在某一任务中将 Pytorch 或者 TensorFlow 模型转化为 ONNX 模型(ONNX 模型一般用于中间部署阶段),然后再拿转化后的 ONNX 模型进而转化为我们使用不同框架部署需要的类型,ONNX 相当于一个翻译的作用。
在微软,所有训练出来的模型,最后都会用 ONNX 格式做线上推理,以简化环境部署,提高推理速度。
#### 要解决的问题
#### 3. 要解决的问题
用户使用各种深度学习框架搭建的模型,互相之间不能互相转换,而且各个框架着重于训练,而在推理方面则速度较慢。ONNX 作为模型推理平台,可以提升速度,简化环境部署依赖。
木头负责其中的 Scikit-Learn 模型到 ONNX 模型的 converter 的维护,也接触了 PyTorch 模型到 ONNX 模型的 converter。还有人负责 TensorFlow 模型到 ONNX 的 converter。主要框架早已经搭建好了,但是在用户使用过程中会发现不少 bug,以 GitHub issue 的形式记录下来,大家认领属于自己领域的 bug 去修复,而这些 bug 绝大多数是前面的开发者遗留下来的。
#### 关于例会
#### 4. 关于例会
Dev manager 在美国,每周一下午(中国时间是周二早晨)开例会,有美国人(分布在东部和西部两个时区)、印度人、中国人、法国人,大家用英语,每个人简单说一下自己在干什么,而且要有 GitHub issue 或者 PR 的 link 来证明。
#### 开发流程
#### 5. 开发流程
- 每半年会重新调整一下工作重点。
@@ -45,7 +45,7 @@ Dev manager 在美国,每周一下午(中国时间是周二早晨)开例
- 有已经搭建好的 CI Pipeline,里面有大量的 UnitTest,每次 check in 代码必须经过 pipeline 的检验,所有 test case 都通过了才能继续。
#### 项目分析
#### 6. 项目分析
从用户需求上看:
@@ -66,7 +66,7 @@ Dev manager 在美国,每周一下午(中国时间是周二早晨)开例
- CI Pipeline 保证了分散开发的灵活性与可靠性。
#### 最终结果
#### 7. 最终结果
- 现在这个项目还在处于发展与维护阶段,解决了用户的大量典型问题,并不断地增加新的组件,让 ONNX 更好用。
@@ -81,7 +81,7 @@ Dev manager 在美国,每周一下午(中国时间是周二早晨)开例
而且要有不同团队直接的合作,所以工作步骤与小型软件完全不同。基本步骤如下:
#### 确定架构
#### 1. 确定架构
如图 5.6.2 左子图所示,经过系统分析后,架构师认为应该把系统的技术栈分成以下五层:
@@ -93,11 +93,11 @@ Dev manager 在美国,每周一下午(中国时间是周二早晨)开例
并且有了相应的原型代码来验证其可行性。
<img src="img/Slide18.JPG"/>
<img src="img/Slide19.SVG"/>
图 5.6.2 中大型系统的开发流程最佳实践
#### 框架实现与接口设计
#### 2. 框架实现与接口设计
如图 5.6.2 中子图所示。
@@ -106,7 +106,7 @@ Dev manager 在美国,每周一下午(中国时间是周二早晨)开例
面向接口的设计可以实现契约式设计,每一层只需要关心对上层提供的接口和需要调用的底层接口。
#### 垂直切片
#### 3. 垂直切片
如图 5.6.2 右子图所示。
@@ -115,7 +115,7 @@ Dev manager 在美国,每周一下午(中国时间是周二早晨)开例
在做垂直切片的实现时,可以考虑使用大粒度的敏捷开发流程。
#### 后续步骤
#### 4. 后续步骤
重复“垂直切片”的步骤,逐步增加功能。
@@ -125,9 +125,9 @@ Dev manager 在美国,每周一下午(中国时间是周二早晨)开例
### 5.6.3 举例
我们仍然用计算器应用这个简单的例子来做说明,并假设它是一个非常复杂的软件,每增加一个按键、一个功能、一个显示字符都很花时间。
我们仍然用计算器应用这个简单的例子来做说明,并**假设**它是一个非常复杂的软件,每增加一个按键、一个功能、一个显示字符都很花时间。
<img src="img/Slide19.JPG"/>
<img src="img/Slide20.SVG"/>
图 5.6.3 中大型系统中的垂直切片
@@ -5,13 +5,13 @@
### 5.7.1 采用合理的开发流程
#### 顺序开发与敏捷开发的对比
#### 1. 顺序开发与敏捷开发的对比
在前面的各节中我们看到,即使是在微软,也会有多种形式的团队流程。原因多种多样,在图 5.7.1 中用表格形式比较了选择传统的顺序开发流程(瀑布模式)和敏捷开发流程的条件。
顺序开发更像是一个交响乐团,需要严密的组织、严格的排练,而敏捷开发更像一个流行乐队,有时候甚至没有谱子,在排练中找感觉,随时调整编曲中的细节。
<img src="img/Slide20.JPG"/>
<img src="img/Slide21.SVG"/>
图 5.7.1 选择不同开发流程的条件
@@ -52,7 +52,7 @@
对于用户不喜欢经常更新的使用环境,比如操作系统和办公软件,就不应该使用敏捷方式,避免出现用户正在给领导做幻灯片演示时,忽然遭遇操作系统升级的尴尬场面。
#### 中大型软件中的敏捷
#### 2. 中大型软件中的敏捷
那么,是不是中大型软件就不能使用敏捷开发的思想呢?不是!以必应搜索服务为例,这是一个超大型的项目,最多时有 3000 多人合作开发:
@@ -62,7 +62,7 @@
- 质的变化发生在 2016 年,不再整体发布了,而是每个 feature team 可以自主发布,最短周期可以是星期。
- 到了 2018 年,随着系统的成熟,完全取消了发布限制,每个 feature team 可以随时发布新功能。
<img src="img/Slide21.JPG"/>
<img src="img/Slide22.SVG"/>
图 5.7.2 必应搜索服务发布周期的演进
@@ -109,7 +109,7 @@
其基本概念如图 5.7.3 所示。
<img src="img/Slide22.JPG"/>
<img src="img/Slide23.SVG"/>
图 5.7.3 三种验证工具的示意图
@@ -124,7 +124,7 @@
|作用|验证技术难点|确认用户需求|及时得到反馈|获得最大收益|
|风险控制|技术实现风险|需求理解风险|整体构建风险|需求、技术、人员、时间、过程等各种风险|
#### PoCProof of Concept)概念验证
#### 1. PoCProof of Concept)概念验证
**目标:验证某个想法是否在技术上是可行的。**
@@ -149,7 +149,7 @@ PoC 的主要目标是测试这个想法在技术上是否可行,是否值得
- 降低尝试去完成一个不可能完成的任务的风险。
#### Prototyping 原型开发
#### 2. Prototyping 原型开发
**目标:以最低成本收集早期反馈。**
@@ -167,7 +167,7 @@ PoC 的主要目标是测试这个想法在技术上是否可行,是否值得
- 分享给甲方,可以尽早得到反馈;
- 降低与预期需求不一致的风险。
#### MVPMinimum Viable Product)最小可行产品
#### 3. MVPMinimum Viable Product)最小可行产品
**目标:尽快、廉价地推出产品,验证假设,收集用户反馈,并迭代。**
@@ -195,7 +195,7 @@ MVP 最小可行产品与 4.6 节中讲的“垂直切片”的概念不完全
所以,最小可行产品是垂直切片的延申。
<img src="img/Slide23.JPG"/>
<img src="img/Slide24.SVG"/>
图 5.7.4 MVP 最小可行产品示意图
@@ -235,39 +235,43 @@ MVP 最小可行产品与 4.6 节中讲的“垂直切片”的概念不完全
解决上述问题的手段就是集成,从一开始就集成,并且不断的集成,反复的将拆分的子系统、模块、组件重新组合,看看是否能够顺利组合起来,并且保证功能的不变。
实现上述不断地集成以及成果物交付的过程就是持续集成和持续交付:
实现上述不断地集成以及成果物交付的过程就是持续集成和持续交付:
1.持续集成:指对代码的提交,构建,测试的过程,这是一个持续、反复的过程。
1.持续集成CI - Continuous Ingegration:指对代码的提交,构建,测试的过程,这是一个持续、反复的过程。
2.持续交付:指将集成好的交付物,例如war、jar或者容器镜像,部署在联调环境,或者预发环境的过程。
2.持续交付CD - Continuous Delivery:指将集成好的交付物,例如 war、jar 或者容器镜像,部署在联调环境,或者预发环境的过程。
以下是本项目采用的一个持续集成、持续交付的过程,研发团队在项目实施过程中要严格遵守:
以下是本项目采用的一个持续集成、持续交付的过程,研发团队在项目实施过程中要严格遵守:
<img src="img/Slide24.JPG"/>
<img src="img/Slide25.SVG"/>
新加了一张图
持续集成、持续交付的基本流程如下:
1. 代码开发,完成分配的任务。
1. 代码开发,完成分配的任务。
2. 每天提交代码,降低代码集成的风险。采用SVN的提交方式,后提交者有责任去merge,保证代码的编译通过和测试通过。
3. 专人定期审核提交的代码,把控代码质量。
2. 每天提交代码,降低代码集成的风险。后提交者有责任去解决冲突,保证代码的编译通过和测试通过。有一些小的项目在这里就可以启动单元测试。
4. 代码审核完毕之后,触发编译过程,完成代码编译
3. 专人定期审核提交的代码,把控代码质量
5. 编译完成,进行单元测试。要求每个类都要有单元测试,并且单元测试覆盖率要达到一定的指标。单元测试要有带Mock的模块内的集成测试。如果单元测试不通过,则统计后发邮件,抄送所有的人
4. 代码审核完毕之后,要 merge 到主分支,然后在主分支上触发编译过程,完成代码编译
6. 单元测试通过以后,上传成果物(war、jar或其它)至Nexus私服
5. 编译完成,进行单元测试。要求每个类/方法都要有单元测试,并且单元测试覆盖率要达到一定的指标。如果单元测试不通过,则不能送审
7. 如果采用私有云,并且使用docker容器,则需要编译Dockerfile,使用Docker镜像作为交付,能够实现更好的环境一致性,保证原子的升级和回滚
6. 单元测试通过,发邮件庆祝一下(可选)
8. 每天下班前,当天的代码需要提交到库中去,晚上会做一次统一的环境部署和集成测试。这个集成测试或者叫回归测试每天晚上都做,都是在一个全新的环境中。如果某一天测试不通过,则会发邮件通知
7. 上传成果物(war、jar、zip、exe等等)至成品仓库
9. 一个周期完毕,进行UAT测试。如果测试不通过,则会发邮件通知,开发人员要及时更正
8. 如果采用私有云,并且使用 Docker 容器,则需要编译 Dockerfile,使用 Docker 镜像作为交付,能够实现更好的环境一致性,保证原子的升级和回滚
10.UAT测试通过以后,准备上线到生产环境。建议采用灰度发布或蓝绿发布机制,分批次发布、切换流量。一般情况下,具有权限的管理人员通过自动化脚本进行部署
9. 每天晚上会做一次统一的环境部署和集成测试。这个集成测试或者叫回归测试每天晚上都做,关注软件功能是否正确,都是在一个全新的环境中。如果某一天测试不通过,则会发邮件通知,开发人员要及时检查问题
通过持续集成、持续交付这套完整的流程,层层保证质量,保证项目可以按时按质的完成,减少项目的实施风险
10. 下面进行压力测试。如果测试不通过,则会发邮件通知,开发人员要及时检查问题
11. 压力测试通过以后,准备上线到生产环境。建议采用灰度发布或蓝绿发布机制,分批次发布、切换流量。一般情况下,具有权限的管理人员通过自动化脚本进行部署。
12. 系统运行过程中收集日志,形成报表,供运营人员检查。
通过持续集成、持续交付这套完整的流程,层层保证质量,保证项目可以按时按质的完成,减少项目的实施风险。
@@ -18,7 +18,7 @@
- Workspace 工作区
你电脑本地看到的文件和目录,在 Git 的版本控制下,构成了工作区。
<img src="img/Slide25.JPG"/>
<img src="img/Slide26.SVG"/>
图 5.8.1 Git 工作流
@@ -58,7 +58,7 @@ Git 的使用流程如下:
先登录 Azure DevOps 网站,建立团队和项目。
<img src="img/Slide26.JPG"/>
<img src="img/Slide27.SVG"/>
图 5.8.2 项目流程类型与主菜单
@@ -66,7 +66,7 @@ Git 的使用流程如下:
#### 2. Backlogs - 创建产品计划
<img src="img/Slide27.JPG"/>
<img src="img/Slide28.SVG"/>
图 5.8.3 待办事项 Backlogs
@@ -87,7 +87,7 @@ Git 的使用流程如下:
#### 3. Boards - 添加具体工作内容并管理
<img src="img/Slide28.JPG"/>
<img src="img/Slide29.SVG"/>
图 5.8.4 工作版内容管理 Boards
@@ -99,7 +99,7 @@ Board 中有四列分栏,分别是 New、Active、Resolved、Closed,状态
#### 4. Sprints - 制定冲刺计划
<img src="img/Slide29.JPG"/>
<img src="img/Slide30.SVG"/>
图 5.8.5 冲刺计划 Sprints
@@ -117,7 +117,7 @@ Board 中有四列分栏,分别是 New、Active、Resolved、Closed,状态
- Dashboards - 仪表板
在主菜单的 Overview 下面。
<img src="img/Slide30.JPG"/>
<img src="img/Slide31.SVG"/>
图 5.8.6 仪表板 Dashboards
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 58 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 50 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 130 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 62 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 60 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 164 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 465 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 329 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 88 KiB

Some files were not shown because too many files have changed in this diff Show More