* update

* Update 3.3 系统化思维能力.md

* Update 2.5 微软的软件工程师.md

* update

* update

* update

* update

* update

* update

* update

* update
This commit is contained in:
xiaowuhu 2023-01-29 16:07:33 +08:00 коммит произвёл GitHub
Родитель 029cbb5027
Коммит cf9022dcfc
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
165 изменённых файлов: 3079 добавлений и 876 удалений

Просмотреть файл

@ -1,4 +1,5 @@
书名:现代软件工程 架构之路
书名:软件工程·最佳实践
作者:胡晓武 ......
@ -21,17 +22,17 @@
理论知识
经验技能
协作能力
最佳实践
### 关于“木头”
#### 关于“木头”
本书中有很多关于“木头”的故事,“木头”是一个虚构的人物,但是 TA 所经历的故事都是在真实事件基础上经过微小改编的,只不过故事的原主人公可能是笔者,也可能是笔者的同事或朋友。
关于乐队
#### 关于乐队
@ -43,6 +44,7 @@
|Architect||
|Backlog||
|Bing Search|必应搜索,微软的全球搜索引擎|
|Bug||
|Career Path||
|Chromium||
|Cortana|微软小娜|
@ -55,10 +57,13 @@
|Feature|特性,是指一组功能的组合所表现出来的产品特性|
|Feature Team||
|Flight||
|Fix Bug||
|FTE||
|Hackathon||
|Happy Hour||
|IC - Indiviudal Contributer|个人贡献者(普通员工或群众,区别于管理者)|
|InfiniBand||
|Instant Answer|即使应答,是一种具有比较丰富的信息与格式的搜索结果|
|INT Bed||
|JD - Job Description|职位描述|
|KA - Knowledge Area|知识领域|
@ -72,6 +77,7 @@
|Promotion||
|PROD Bed||
|RSDE||
|Root Cause||
|SDE||
|Solo||
|Spot Reward||
@ -79,6 +85,7 @@
|Test Bed||
|Transfer||
|NLP||
|URL||
|UX - User Experience||
|UWP|Universal Windows Platform|
|Vendor|

Просмотреть файл

@ -0,0 +1 @@
## 1.6 练习

Просмотреть файл

@ -1,14 +1,17 @@
career
windows phone
uwp
boss
<img src="img/Slide1.SVG"/>
<img src="img/Slide1.JPG"/>
做一名合格的软件工程师所需要的专业技术能力有:
(插入一些说明性文字,重点在介绍上下文,串连)
- 算法algorithm
- 代码coding skill
- 建模design pattern
- 设计system design
- 测试testing
<img src="img/Slide2.JPG"/>
本章将会就这几个专业能力展开讨论。
<img src="img/Slide2.SVG"/>

Просмотреть файл

@ -8,7 +8,7 @@
木头加入微软就是走的 Industry Hire 渠道,只要不是刚踏出校门的学生寻找第一份工作,就都要走这个渠道。简历能被 HRHuman Resoruce人力资源看到是一件非常幸运的事如何写简历不在本书的讨论范围之内。木头就很幸运几个关键的技术点正好符合 JDJob Description职位描述于是才有了下面的故事......
<img src="img/Slide3.JPG"/>
<img src="img/Slide3.SVG"/>
### 2.1.1 第一轮面试

Просмотреть файл

@ -10,7 +10,7 @@
故事就写到这里吧,下面总结一下微软这样的公司需要什么样的人做 SDE。
<img src="img/Slide4.JPG"/>
<img src="img/Slide4.SVG"/>
### 2.2.1 技能点是否符合 JD 要求
@ -18,7 +18,7 @@
做为一个 Industry Hire Candidate即有多年从业经验的面试者写简历的基本技巧如下
#### 让 HR 能够一眼看到关键字
#### 1. 让 HR 能够一眼看到关键字
因为简历都是通过 HR 筛选出来的,而大部分 HR 是不懂技术的Ta 们每天面对大量的简历,首先就是要通过关键字来匹配岗位需要和面试者的经验或技术能力。
@ -26,7 +26,7 @@
- 设计能力和经验,比如大数据存储与处理经验、复杂系统搭建经验、大用户量的并发访问设计经验、训练神经网络模型的经验、手机应用开发的经验等等。
- 一些著名的服务组件或框架的使用经验,比如 Web 服务器中的 Appache、消息队列中的 RabbitMQ、数据库 MySQL、分布式系统架构 Hadoop 等等。
#### 让技术面试官能看到项目经验
#### 2. 让技术面试官能看到项目经验
技术面试官通常不会被关键字所迷惑,而是看面试者的具体项目经验。在每一个项目介绍中,应该包含一下内容:
@ -36,7 +36,7 @@
- 项目实施结果,比如上线后的用户反馈情况、如何更新升级功能、如何降低维护成本等等。
- 遇到的困难及解决方案,由于内容较多所以通常不会写在简历里,但是面试者要准备好面试官的询问。
#### 让老板能看到能力特点
#### 3. 让老板能看到能力特点
具有同等技术能力的面试者有很多,如果都能通过前面的技术面试的话,老板为什么会选择你?通常下面几点会影响老板的决策:
@ -45,7 +45,7 @@
- 在前面每个公司任职的时长,会预测你在新公司是否稳定,两年里换了三个公司的人,一般老板是不敢要的。
### 2.2.2 沟通能力Communication Skill
### 2.2.2 面试时的沟通
面试刚开始时,面试官一般都让你聊一聊自己的项目,并且时不时地插问几个问题,实际上就是看看你的表达能力如何。当今的软件规模很大,没有那种一个人可以搞定的,需要团队配合,所以沟通能力很重要。
@ -55,11 +55,11 @@
自我介绍是面试过程中必经的一个环节,一段精彩的自我介绍是面试成功的基础,它决定着面试官对候选人的第一印象,也为接下来的面谈定下基调。
#### 第一印象很重要
#### 1. 第一印象很重要
面试官通过简历和候选人的自我介绍可以快速了解和掌握候选人的行业背景、经历、表达能力、逻辑思维能力、英语水平等。其实在面谈开始的1到2分钟内面试官就已经有了初步的判断这个候选人是否适合这个岗位而后面展开的一系列的问题和探讨都是在验证自己的这个判断当然也存在在过程中改变的情况。所以第一印象很重要一定要好好准备开场的自我介绍。
#### 自我介绍如何准备
#### 2. 自我介绍如何准备
1. 内容要有重点
@ -85,7 +85,7 @@
### 2.2.3 面试中的技术问题
#### 算法与代码能力Algorithm and Coding Skil
#### 1. 算法与代码能力Algorithm and Coding Skil
第三个面试官是一个Dev Lead他会着重在算法和 Coding Skill代码能力上。
@ -102,7 +102,7 @@
这个题目一般人都会想到用两个指针从字符串两头向中间移动,所以算法并不难,只是考察代码能力。
#### 设计能力Design Skill
#### 2. 设计能力Design Skill
第四个面试官是 Dev Manager他会着重在算法和设计能力上。
@ -111,7 +111,7 @@
- 如何给一个十字路口的红绿灯系统建模,这个问题稍微复杂一些了,要对对象、行为、外部控制等建模。
- 给一个会议室建模。
#### 测试能力Testing Skill
#### 3. 测试能力Testing Skill
第二个面试官问过关于手机测试的问题。关于“测试”有两个误区:
@ -128,7 +128,7 @@
相对一技术能力,以下能力可以称之为“软能力”:解决问题的能力,系统化思维能力,学习能力。
#### 解决问题的能力Problem Solving
#### 1. 解决问题的能力Problem Solving
一般情况下,面试官会把这种能力与算法编码能力以及设计能力混淆,因为他们认为一个面试者的解决问题的能力就应该体现在编码和设计上。但其实笔者认为这是两个领域的问题,解决问题的能力,应该处于更高层次,是一种可以普遍适用的能力。
@ -136,7 +136,7 @@
这种能力何时使用呢?领导交给你一个任务,其中会有很多困难,有一些环节有成熟的解决方案,有些环节没有任何前人经验和参考资料,需要你抓住重点和主线,一个一个地解决它们,为最终完成任务铺平道路。
#### 系统化思维能力Systematic Thinking
#### 2. 系统化思维能力Systematic Thinking
从旁观者看来木头遇到的这些面试题并不难面试官主要是考察木头的思维习惯以及在压力面前的表现而不是用一个很难的题目难倒面试者。Skill技能当然要具备Passion激情和 Potential潜力是最重要的。
@ -148,7 +148,7 @@
- 如果一个团队 4 个年轻人,有男有女,骑车环游中国边界省份,大概需要多长时间完成一圈?
- 为什么民间有“八月十五云遮月,正月十五雪打灯”的说法?
#### 学习能力Learning Ability
#### 3. 学习能力Learning Ability
学习能力从一个小时的面试过程中是看不出来的,只能从面试者的经历中做判断。最后一个面试官就是 AA他可以从木头在语音增值业务系统上的经验和自学游泳的四种泳姿的经历中考察木头的学习能力。
@ -163,7 +163,7 @@
以下是一位来自微软 M365 团队的技术经理的分享(偏口语化)。
#### 过往项目经历
#### 1. 过往项目经历
过去的项目经历,并不只是了解你做了什么,很多时候我们更希望知道你的独特的贡献是什么?因为很多时我们都是在“团队环境”下工作,你独特的贡献是什么?以及你遇到的独特的挑战和你怎么独特地解决这些挑战的?这些东西是可以在你们在面试的过程中需要特别的强调的。
@ -171,17 +171,17 @@
其实不用讲太多,讲一些独特性就可以了。
#### 算法
#### 2. 算法
针对软件工程师,我们一定会考察算法,当然算法大家也不用太害怕,我们其实更多的看重是你解题的思路。这种算法一般都是不难找到一个解决办法,但是我们更多的是看你能不能基于一个解决办法能够去调优,能够找到一个更优化的办法。所以很多题目都是有一个相对比较简单能够解出来的办法,但是同时也会有需要一些思考才能够想到的一个优化的办法。所以我们很多时候是希望看到你的解题的思路和过程,因为其实我们目的并不是要考住你。
#### 系统设计
#### 3. 系统设计
我们针对比较 Senior 职位也会考察一下Systsem Design会有些开放式的 Design 的问题比如说设计一个这个网盘系统啊Message Queue 的系统设计呀,比如说像那个推特这种这种发消息和订阅消息的这样的一个系统啊,我发一条消息,然后所有的人都能搜到。其实就是考察大家系统设计。
要注意分布式系统设计系统架构的。你可能要考虑到这个系统你怎么保证高可用啊你怎么做灾备啊你怎么做异地多活啊你怎么保证数据的可用性啊你怎么保证你的不同的区域的用户都能够Low Latency地访问啊等等会考察大家的这个这种分布式系统环境下的这种思考。
#### 文化
#### 4. 文化
当然在文化上面呢,我们可能会问大家对多元和包容的理解啊,以及你是怎么做的。因为这个多元包容,不只是管理者,其实很多时候涉及到,每个人每个人都要多元和包容。

Просмотреть файл

@ -2,7 +2,7 @@
在木头的面试中,有过这样一道题,如图 2.3.1 所示。
<img src="img/Slide5.JPG"/>
<img src="img/Slide5.SVG"/>
图 2.3.1 算法与代码能力
@ -109,7 +109,7 @@ def method_3_sort(data):
4. 从位置 1 取出数字 5放到位置 5
5. 从位置 5 取出数字 1放到位置 1但发现位置 1 上已经是 1 了,是重复数字。
<img src="img/Slide6.JPG"/>
<img src="img/Slide6.SVG"/>
图 2.3.2 追溯法

Просмотреть файл

@ -1,6 +1,6 @@
## 2.4 建模与设计能力
<img src="img/Slide7.JPG"/>
<img src="img/Slide7.SVG"/>
图 2.4.1 建模
@ -210,7 +210,7 @@ class RibukCube():
这个问题需要有一定的系统设计能力了
<img src="img/Slide8.JPG"/>
<img src="img/Slide8.SVG"/>
图 2.4.2 股票预测系统设计

Просмотреть файл

@ -1,55 +1,55 @@
## 2.5 软件工程师在微软
### 2.5.1 定义、级别、职务
### 2.5.1 定义、级别、角色
#### 定义 Definition
#### 定义Definition
微软是这样定位软件工程师的:
微软是这样定位软件工程师的(英文原文)
*Software Engineers take end-to-end ownership for development and quality of products and services that delight customers and add strategic value to Microsoft. They evaluate requirements, estimate costs, and design and implement products and services. They define and implement the quality criteria for their products and services, using measurements and insights to understand and validate the quality of experience for customers. They manage and improve the engineering process, manage risks, dependencies and compromises, and integrate software into broader ecosystems and/or products and services.*
软件工程师负责端到端的产品和服务的开发和质量以让客户满意并为Microsoft增加战略价值。
软件工程师负责端到端的产品和服务的开发和质量,以让客户满意并为 Microsoft 增加战略价值。
- 评估需求,估算成本,设计和实施产品和服务。
- 他们定义并实施产品和服务的质量标准,通过有效的衡量手段和细致入微的观察来理解和验证用户体验的质量。
- 定义并实施产品和服务的质量标准,通过有效的衡量手段和细致入微的观察来理解和验证用户体验的质量。
- 管理和改进工程过程,管理风险,捋顺依赖链条,必要时采取折中方案,将软件集成到更广泛的生态系统和/或产品和服务中。
#### 阶段 Stage
#### 阶段Stage
微软的软件工程师的级别划分如图 2.5.1 所示。
微软的软件工程师的阶段划分(级别)如图 2.5.1 所示。
<img src="img/Slide9.JPG"/>
<img src="img/Slide9.SVG"/>
图 2.5.1 微软软件工程师的级别
从阶段看,一共有 9 个,所以后面会简称为“几段”(类似围棋选手级别名词)。在有些区域是有“一段”的,比如微软苏州,但是微软北京都是从“二段”开始。
从阶段看,一共有 9 个,所以后面会简称为“几段”(类似围棋选手级别名词)。在有些区域是有“一段”的,比如微软苏州,但是微软北京都是从“二段 (Stage 2)”开始。
在以前的官方定义中,软件工程师的英文名称为 Software Development软件开发后来改成了 Software Engineer软件工程师笔者猜测其原因如下
1. 在微软取消了测试职位后软件工程师也要负责测试所以不能再叫做Development 了,但是又不能叫做 Software Development-Test所以就叫做 Software Engineer
1. 在微软取消了测试职位后,软件工程师也要负责测试,所以不能再叫做 Development 了,但是又不能叫做 Software Development-Test所以就叫做 Software Engineer
2. Software Development 只负责开发Software Engineer 在字面上加入了工程的含义,即对软件开发者有更高的要求,需要熟悉产品周期各个环节的所有职责。
还有一个级别Level的概念比如
- 在二段中有 5960 两个级别;
- 在三段中有 61、62 两个级别;
- 在四段中有 63、64 两个级别;
- 在五段中有 65、66、67 三个级别;
- 在二段中有 L59L60 两个级别;
- 在三段中有 L61、L62 两个级别;
- 在四段中有 L63、L64 两个级别;
- 在五段中有 L65、L66、L67 三个级别;
......
#### 角色 Discipline
#### 职业Discipline
Discipline 原意是知识领域,可以引申为角色。前面也说过,在微软与软件开发有关的有以下几种主要的角色:
Discipline 原意是知识领域,可以引申为职业。前面也说过,在微软与软件开发有关的有以下几种主要的职业角色:
- SE/SDE 软件工程师
- PMProgram Manager项目经理
- Designer 设计师
#### 职务 Role
#### 角色Role
有三种职务
有三种角色
- ICIndividual Contributer个人贡献者表示不管理任何人的工程师,因为有些人即使到了技术专家级别也不想走管理路线。
- ICIndividual Contributer个人贡献者表示不管理任何人因为有些人即使到了技术专家级别也不想走管理路线。
- Lead小领导管理几个 IC这些 IC 的级别通常都比该 Lead 要低或者同级。
@ -57,142 +57,205 @@ Discipline 原意是知识领域,可以引申为角色。前面也说过,在
- Manager大领导管理 IC 和 Lead 并有 Report 关系,一般具有 Principle 段位。
### 2.5.2 主要工作考核指标
### 2.5.2 考核指标
微软对软件工程师的主要考核有六个大项,如图 2.5.2 所示。
微软对软件工程师的要求有六个大项,如图 2.5.2 所示。
<img src="img/Slide10.JPG"/>
<img src="img/Slide10.SVG"/>
图 2.5.2 微软工程师的考核指标
下面以“二段”为例,介绍一下每个大项中包含的具体内容。
#### Product and Service Design - 产品和服务设计
#### 1. Product and Service Design - 产品和服务设计
构建正确的产品和服务,为客户提供预期价值,并实现所需的业务目标。根据客户洞察力(数据驱动)和总体业务目标制定决策。
构建正确的产品和服务,为客户提供其预期的价值,并实现所需的业务目标。根据对客户系统运行数据的观察总结和总体业务目标制定决策。
对于“二段”,有以下具体要求:
对于“二段”,有如图 2.5.3 所示的具体要求:
<img src="img/Slide11.JPG"/>
<img src="img/Slide11.SVG"/>
图 2.5.3 产品和服务设计
从内容上看,这一项要求软件工程师具备 PM 的一些基本素质,这里的“设计”不是技术上的,而是功能上的。需要在横向上对产品和服务的有基本的了解,在纵向上对上下游合作者有基本的了解。
- 熟悉产品或服务、竞争对手产品或服务的工作知识,以及客户或合作伙伴的知识,为创新功能区产品或服务设计做出贡献。
- 就产品或服务设计提供反馈,具有吸引客户的风格、趣味性和美感,以及功能需求。
- 找到自己在产品或服务设计交付中的角色,充分发挥自己的作用。
- 根据业务需求进行迭代和更改的设计。
#### Technical Design and Implementation - 技术设计和实现
【最佳实践】
开发高质量的代码以满足技术要求例如可伸缩、全球交付、分布式、可监控、可维护性、可测试性、调试和维护。构建关联的测试以在单元级别和端到端级别验证代码。开发满足预期投资回报ROI的基础设施。使用技术软件开发技能来识别问题并提倡改进产品或服务设计。
- 每个软件工程师不能一叶障目不见泰山,只看得见眼前的代码,但看不见软件产品的整体面貌。要求软件工程师具备 PM 的一些基本素质,这里的“设计”不是技术上的,而是功能上的。比如想开发一个新的功能,其用户交互入口应该放在什么地方,才能既不破坏原有界面不违和,又能够让用户发现新功能。
- 需要在横向上对现有的产品和服务以及竞争对手有基本的了解,比如 Bing 搜索服务,你要知道微软自己的 Bing 都能提供什么功能,还要知道竞争对手如 Goole 和百度都能提供什么功能。
- 在纵向上对上下游合作者有基本的了解,比如作为界面开发者,你需要知道上游的业务都需要展示什么功能,还需要知道给下游的数据采集都提供什么接口。
- 在时间轴上还要掌握产品的迭代规律和方向,比如在满足了用户的基本搜索需求后,是不是要提供合适的广告来增加收益,同时又不引起用户反感。
对于“二段”,有以下具体要求:
对于这个阶段的软件工程师而言,
<img src="img/Slide12.JPG"/>
#### 2. Technical Design and Implementation - 技术设计和实现
开发高质量的代码以满足技术要求例如可伸缩、全球交付、分布式、可监控、可维护性、可测试性、调试和维护。构建关联的测试以在单元级别和端到端级别验证代码。开发满足预期投资回报ROI的基础设施。使用软件开发技能来分析解决问题并改进产品或服务的技术设计。
对于“二段”,有如图 2.5.4 所示的具体要求:
<img src="img/Slide12.SVG"/>
图 2.5.4 技术设计和实现
这一项要求首先有设计,哪怕是很简单的设计,或者口头交流,得到大家的认可之后,再继续进行开发工作。对于这个阶段的软件工程师而言,应该是使用已经定义好的接口进行局部功能的设计与开发,尽量通过看代码、查文档、向资深同事咨询等方式,来充分了解技术背景。
- 针对各类不同的问题,进行层次设计和接口设计,实现组件组之间的集成,提高重用性,并满足业务、客户、工程和运营需求。
- 在适当的时候推动设计评审,定义模块之间的接口,并将成熟技术应用于设计。
- 考虑可诊断性、可移植性/监控、可靠性和可维护性,并知道分享和交付代码的最佳时机。
- 遵守代码编写规范。
- 利用来自客户和生产部门的数据和分析,为一些技术设计和实施决策提出建议。
#### Quality Code and Validation - 代码质量和验证
【最佳实践】
创建并验证高效(低延迟、高吞吐量)、稳定、安全、可维护、可扩展、性能好、经过良好测试和可重用的代码,以实现产品或服务的客户和业务目标。构建正确的测试和工具,以验证代码是否符合质量目标或服务。分析数据并给出结论,使自己和同事能够在适当的时候理解和解决问题。确保在产品或服务的整个生命周期内保持质量。
- 这一项要求强调了设计的重要性,哪怕是很简单的设计,或者口头交流,得到大家的认可之后,再继续进行开发工作。
- 对于这个阶段的软件工程师而言,应该是使用已经定义好的接口进行局部功能的设计与开发,尽量通过看代码、查文档、向资深同事咨询等方式,来充分了解技术背景,别自己瞎猜,不但耽误时间,猜错了还会耽误事。
- 强调了代码质量的重要性,在现阶段主要是让别人审查自己的代码,在代码风格、命名规范、与已有代码的契合程度等方面符合项目组的代码编写规范,同一个错误不能犯两次。比如在代码审查时,同事给你指出了一个变量命名错误,那么以后在命名变量时就不要太随意。
- 懂得数据收集与统计分析的重要性,并学会分析的方法。
对于“二段”,有以下具体要求:
#### 3. Quality Code and Validation - 代码质量和验证
<img src="img/Slide13.JPG"/>
创建并验证高效(低延迟、高吞吐量)、稳定、安全、可维护、可扩展、性能好、经过良好测试和可重用的代码,以实现产品或服务的客户和业务目标。构建正确的测试和工具,以验证代码是否符合质量目标或服务。分析数据并给出结论,使自己和同事能够理解和解决问题。确保在产品或服务的整个生命周期内保持质量。
对于“二段”,有如图 2.5.5 所示的具体要求:
<img src="img/Slide13.SVG"/>
图 2.5.5 代码质量和验证
这一项强调了代码 review审查的重要性一方面要审查别人的代码另一方面让别人审查自己的代码主要是在代码风格、命名规范、与已有代码的契合程度等方面。另一方面代码逻辑的正确性需要由单元测试做保证也避免将来别人新加入的代码破坏你的代码逻辑。
- 考虑性能和可维护性,了解代码何时可以分享或交付,可以处理该产品各个方面的问题。
- 解决测试覆盖率问题,组织和实施集成测试,并修复发生问题的代码。
- 获得功能设计和编写代码的技术知识,以识别风险并防止错误。
- 发现缺陷时,给出充足的证据来描述缺陷本身,说明缺陷对某些功能的影响,以及对应用场景和质量目标的影响。
- 具备数据知识,知道需要什么日志数据,如何查找新的或丢失的数据,以及它们与产品和服务目标的相关性。
【最佳实践】
#### Engineering Lifecycle - 工程生命周期
- 对所有的代码增加单元测试,代码逻辑的正确性需要由单元测试做保证,也避免将来别人新加入的代码破坏你的代码逻辑。
- 对于代码测试覆盖率有要求,比如是 80% 还是 90% 才能达标?增加单元测试的项目以便提高覆盖率。如果当时嫌麻烦而少写了几条单元测试,后面新加的功能很可能会破坏现有逻辑。
- 发现 Bug 后要很负责地提供详细的信息,或者是找到该功能的负责人,告知对方自己发现的 Bug演示如何复现这个 Bug以及它带来的不良后果。
- 最后还要有日志技术的知识,可以设计如何产生日志,以及日志可以反应的具体功能点的好坏。比如用户经常抱怨某个功能的响应速度太慢,那么就要为此功能多加几层日志,以了解各个环节的运行时间,找到瓶颈所在。
使用、定义和改进编码和测试实践、流程、工具、基础架构和标准以提高效率为Microsoft和客户提供预期的产品或服务成果。
#### 4. Engineering Lifecycle - 工程生命周期
对于“二段”,有以下具体要求:
使用、定义和改进编码和测试实践、流程、工具、基础架构和标准,以提高效率,为 Microsoft 和客户提供预期的产品或服务成果。
<img src="img/Slide14.JPG"/>
对于“二段”,有如图 2.5.6 所示的具体要求:
<img src="img/Slide14.SVG"/>
图 2.5.6 工程生命周期
- 利用对工程生命周期和以往发布产品经验的理解,倡导在每个里程碑上提出改进建议,以及整个过程的改进。
- 在适当的情况下,推动设计和代码审查,并在整个团队中分享最佳实践。
- 参与设计和代码评审,分享最佳实践。
这一项把代码和工程结合起来,相当于是软件工程的具体实践。
【最佳实践】
#### Effective Team - 高效的团队合作
- 要学习软件工程的基本概念和操作过程,书本上的知识是远远不够的。
- 在实际发布软件产品时,会发现很多细节问题,向资深同事了解详细的发布过程,有必要的话把它们记录下来,下一次发布时就会不遗漏任何步骤。
- 当你觉得在某个环节上有理解障碍或者没有具体的行动指南时,就要提出来。比如在团队中工作的老员工都知道多写注释少写文档,而你在别的项目中得到的信息是多写文档少写注释,这时就要及时询问领导,或者给出你的选择理由。
- 在刚加入团队时,可以要求其它老同事多分享最佳实践,这样可以帮助你尽快融入团队。自己有一些心得后,也应该及时分享,别藏着掖着的拿自己当外人。
#### 5. Effective Team - 高效的团队合作
在团队环境中积极行动,提高团队整体的效率、影响力和士气。跨团队、产品、服务或平台边界积极工作,以共享信息和技术,并确保同行团队目标一致。酌情组建团队。指导他人并主动寻求他人的指导。
对于“二段”,有以下具体要求:
对于“二段”,有如图 2.5.7 所示的具体要求:
<img src="img/Slide15.JPG"/>
<img src="img/Slide15.SVG"/>
图 2.5.7 高效的团队合作
在团队环境中积极行动,提高团队整体的效率、影响力和士气。跨团队、产品/服务或平台边界积极工作,以共享信息和技术,并确保同行团队目标一致。
- 在团队中做出建设性贡献。
- 主动管理依赖关系并展示解决冲突的能力。
- 努力在整个团队中以适当的详细程度和及时性向合适的受众持续共享信息。
- 提升团队士气。
- 积极寻求他人的指导。
- 不断寻求并提供反馈。
- 分享改善团队效率的想法。
其中第三条是比较难做到的:当你意识到有些信息其它人不知道时(这一点本身就很难),需要主动地告知他人(一般人会选择等着别人来问)。
【最佳实践】
#### Product and Service Ownership - 对产品和服务的责任感
- 少发牢骚,不抱怨现有困难,而是要想办法解决困难,多提建设性的意见。比如大家共享的一个服务器运行速度很慢,你发现有个同事经常跑一些运算量很大的任务,长时间占用计算资源,你可以向领导提出多增加几个虚拟机的要求,进行物理隔离,这样每个人的任务都不会影响其它人。
- 当你意识到有些信息其它人不知道时(这一点本身就很难),需要主动地告知他人(一般人会选择等着别人来问)。比如你发现了大家都在使用的一个工具有个 Bug 会导致运行结果不对但又很难发现,你应该及时群发邮件告知大家这个信息。
- 有时候顾于面子不愿意向他人请教,而是自己花时间在那里抠细节。此时如果先放下面子问一下相关同事,就会得到一些基本的概念和行动指南,避免绕路或者重新发明轮子。
#### 6. Product and Service Ownership - 对产品和服务的责任感
持续而有力地显示出对整个产品或服务的质量和完整性以及最终用户体验的责任感。保持一种自豪感和工艺感,使我们的产品具有美感和技术价值。
<img src="img/Slide16.JPG"/>
对于“二段”,有如图 2.5.8 所示的具体要求:
<img src="img/Slide16.SVG"/>
图 2.5.8 对产品和服务的责任感
- 对端到端的产品或服务质量、完整性以及产品或服务生命周期中的最终用户体验具有自豪感、承诺感和个人责任感。
- 定期使用产品/服务,彻底了解产品/服务并找出改进方法。
- 确保设计美观、用户体验简单、优雅、实用。
- 在其职责范围之外,积极协作并为问题的解决做出贡献,以确保最高水平的质量。
- 表现出对产品/服务使用质量的坚定承诺,并在产品或服务的整个生命周期内采取适当措施解决问题。
【最佳实践】
- 这一项主要是强调态度,让员工和自己所负责的产品融为一体,有主人翁的责任感。其实,以员工自身而言,要想获得更多的工作经验和更高的职位,就应该热爱自己的产品,全身心投入。产品给力,客户评价好,自然就晋升得快,对客户、对公司、对自己,三方都有好处。
- 在提出自己的意见时也要注意不要过分热心,不顾及其它人的感受。比如,你觉得有个界面的配色太丑了,你不能直接对 Designer 说“你的设计太丑了”,而是要拿出具体的改进意见和对方讨论。
- 在修改某个代码片段时,一定要找到该代码的原始作者,与之商量后再改,不能越俎代庖,抢占他人的“地盘”。
### 2.5.3 技术设计与实现的进阶
在 2.5.1 小节中描述的都是针对“二段”软件工程师的要求,
上一小节中描述的都是针对“二段”软件工程师的要求,内容看上去已经比较丰富了,但其实还是入门级别。针对更高级别的软件工程师的级别如图 2.5.9 所示,这里只用“技术设计与实现”一项来举例。
<img src="img/Slide17.JPG"/>
<img src="img/Slide17.SVG"/>
图 2.5.9 技术设计与实现的进阶
#### SDE - 模块级别
#### 1. SDE - 解决模块级别的简单技术问题
要求:
- 开发解决各类问题的完整设计和测试接口,实现组件组之间的集成,提高重用性,并满足业务、客户、工程和运营需求。
- 在某些情况下,推动设计审查,定义代码模块之间的接口,并将现有技术应用于设计。
- 考虑可诊断性、可移植性/监控、可靠性和可维护性,并了解代码何时可以共享和交付
- 应用编码模式和最佳实践
- 利用来自客户和生产部门的数据和观察,为一些技术设计和实施决策做出贡献
- 针对各类不同的问题,进行层次设计和接口设计,实现组件组之间的集成,提高重用性,并满足业务、客户、工程和运营需求。
- 在适当的时候推动设计评审,定义模块之间的接口,并将成熟技术应用于设计。
- 考虑可诊断性、可移植性/监控、可靠性和可维护性,并知道分享和交付代码的时机
- 遵守代码编写规范
- 利用来自客户和生产部门的数据和分析,为一些技术设计和实施决策提出建议
说明:
【最佳实践】
在 SDE 级别,主要是在软件的模块级别上工作,只为自己编写的局部功能负责。
在 SDE 级别,主要是在软件的**模块级别**上工作,只为自己编写的局部功能负责。模块是否能正常工作是重点要关心的。
#### SDE II - 组件级别
#### 2. SDE II - 解决组件级别的复杂技术问题
要求:
- 开发完整的设计和测试接口,以解决各类问题,实现组件组之间的集成,改进重用,并满足业务、客户、工程和运营需求。
- 推动所在项目的设计审查,定义代码模块之间的接口,并将现有技术应用于设计。
- 考虑可诊断性、可移植性/监控、可靠性和可维护性,并了解其代码何时可以共享和交付
- 应用编码模式和最佳实践。
- 利用来自客户和生产部门的数据和观察,为一些技术设计和实施决策做出贡献。
- 针对各类不同的问题,进行层次设计和接口设计,实现组件组之间的集成,提高重用性,并满足业务、客户、工程和运营需求。
- 推动所在项目的设计审查,定义模块之间的接口,并将成熟技术应用于设计。
- 考虑可诊断性、可移植性/监控、可靠性和可维护性,并知道分享和交付代码的时机
- 遵守编码规范和最佳实践。
- 利用来自客户和生产部门的数据和分析,为一些技术设计和实施决策做出贡献。
说明:
【最佳实践】
在 SDE II 级别,主要是在软件的组件级别上工作,对所在的项目负有一定的责任。
在 SDE II 级别,主要是在软件的**组件级别**(模块的组合)上工作,对所在的项目负有一定的责任。要关心的组件的对外接口的正确与稳定。
#### Senior SDE - 功能级别
#### 3. Senior SDE - 解决功能级别的端到端技术问题
要求:
- 开发优雅的设计和测试,以识别和消除产品或服务范围内的问题,并与多版本产品或服务计划和功能区架构保持一致
- 推动整个团队的设计审查,并应用可用技术的专业知识。
- 在团队中以身作则,生成简单、可扩展和可维护的代码,缺陷极少。查找并修复缺陷类别
- 确保一致、可用、前瞻性、可维护的测试基础设施,从大量设计模式中汲取经验,是可用技术方面的专家,并且擅长识别有效的实践
- 用指标来提高代码的质量和稳定性。
- 利用来自客户和生产部门的数据和观察,做出功能区技术设计和实施决策。
- 做出优雅的设计和测试框架,发现和解决产品或服务范围内的问题,并与多版本产品或服务计划和功能区架构保持兼容
- 推动整个团队的设计审查,具备使用成熟技术的专业知识。
- 在团队中以身作则,生成简单、可扩展和可维护的代码,缺陷极少。查找并修复各类缺陷。
- 确保一致、可用、前瞻性、可维护的测试基础设施,从大量设计模式中汲取经验,是可用技术方面的专家,并且擅长总结有效的实践经验
- 用指标来衡量并提高代码的质量和稳定性。
- 利用来自客户和生产部门的数据和分析结果,做出功能区技术设计和实施决策。
说明:
【最佳实践】
在 Senior SDE 级别,主要是在软件的功能级别上工作,对某个产品或服务的端到端功能负有责任。
在 Senior SDE 级别,主要是在软件的**功能级别**(组件的堆叠)上工作,对某个产品或服务的端到端功能负有责任。功能的完整性、正确性是要关心的事情。
#### Principle SDE - 系统级别
#### 4. Principle SDE - 解决系统级别的综合性技术问题
要求:
@ -201,13 +264,13 @@ Discipline 原意是知识领域,可以引申为角色。前面也说过,在
- 领导验证产品或服务或架构创新的工作,确定开发过程早期的关键设计领域和下游需要改进的领域。
- 选择适当的内部或外部技术,整合研究,创建设计和验证工具,包括在团队中重用的测试自动化,是对有效实践的优秀判断。
- 定义或重用质量指标、最佳实践和编码模式,以确保代码可测试。
- 利用来自客户和生产部门的数据和观察做出技术设计和实施决策。
- 利用来自客户和生产部门的数据和分析结果做出技术设计和实施决策。
说明:
【最佳实践】
在 Principle SDE 级别,主要工作在软件的系统级别上,对某个产品或服务的整体负责。
在 Principle SDE 级别,主要工作在软件的**系统级别**(功能的组合)上,对某个产品或服务的整体负责。产品是否可以满足各种用户的整体要求、为公司增加商业价值是要关心的事情。
#### Partner SDE - 部门级别
#### 5. Partner SDE - 部门级别的创新设计
要求:
@ -216,24 +279,34 @@ Discipline 原意是知识领域,可以引申为角色。前面也说过,在
- 将质量融入自己的设计,并贯穿整个部门。
- 解决跨越多个版本的产品/服务或部门的最复杂问题。
说明:
【最佳实践】
Partner SDE 级别已经不能再用软件的级别来对标了,而是要负责一个部门中的好几个产品或服务。
Partner SDE 级别已经不能再用软件的级别来对标了,而是要负责一个**部门**中的好几个产品或服务。产品发展方向以及在公司产品线中的地位是这个级别最应该关心的事情。
#### Distinguished Engineer - 部门/公司
杰出的工程师代表着对微软的持续技术影响和影响力。个人需要深厚的技术知识、领导力和专业领域的重大创新。在各自的领域,对部门的业务成功至关重要,并负有责任,可能会塑造行业。
#### 6. Distinguished Engineer - 组织级别的产品方向
要求:
- 作为其专业领域/领域的技术权威,为其专业领域的部门、公司或行业制定方向或技术路线图。
- 无论组织或权力如何,都会影响技术业务决策。
- 跨部门、公司或行业工作,以增加其专业技术领域的价值。
- 在做出技术决策时,要考虑到部门和公司战略,而不是个人/团队的利益。
- 通过教学、参与、指导、建议和领导建立未来的技术社区。
- 体现了“一个微软”和“一个工程文化”。
- 体现了“一个微软 (One Microsoft)”和“一个工程文化(One Engineering Culture)”。
- 展示微软的领导原则、文化属性和价值观。
#### Technical Fellow - 公司/行业
【最佳实践】
该名称仅适用于公司高管层相当于CVP
杰出工程师代表着对微软的持续技术影响和影响力。个人需要深厚的技术知识、领导力和专业领域的重大创新。在各自的领域,对**组织**的业务成功至关重要,并负有责任,可能会塑造行业
代表着对微软最高水平的持续技术影响和影响力。个人需要卓越的技术知识、领导力和专业领域的重大创新。在各自的领域,对微软持续的商业成功至关重要,并对其负责,他们往往塑造着整个行业。
#### 7. Technical Fellow - 公司级别的重大创新
要求:
- 代表着对微软最高水平的持续技术影响。
- 本人需要具备卓越的技术知识、领导力和专业领域的重大创新。
- 在各自的领域,对微软持续的商业成功至关重要,并对其负责,他们往往塑造着整个行业。
【最佳实践】
该头衔仅适用于公司高管层相当于CVP需要对**公司**级别的产品方向负责。

Просмотреть файл

@ -0,0 +1,190 @@
## 2.6 软件工程师的常见误区
软件工程师的常见误区如图 2.6.1 所示。
<img src="img/Slide18.SVG"/>
图 2.6.1 软件工程师的常见误区
### 2.6.1 重新发明轮子,浪费时间
这是个老生常谈的话题“反复造轮子”Reinvent The Wheel。新程序员总是喜欢反复“造轮子”其原因不外乎以下几点
- 自认为当前的实现不够好,所以不得不从头重写整个东西;
- 对某个现有产品缺乏信任,怕在使用过程遇到麻烦;
- 不想花时间去学习别人给定的框架、约束、接口等等,认为自己写一个新的更快、更有趣;
- 想体现自己的价值。
很多年前,笔者的一个朋友认为 Windows Forms UI 控件实在是太简单了,不能满足复杂的应用,原始他想重新编写自己的 UI 控件,并花费了大量的时间。最后,他造的 GUI 工具被商业化成体系的 .Net UI 控件轻松打败,他唯一能获得的只是经验,当然还可以和儿子吹一吹当年与微软竞争的故事(虽然微软并不知道有这么一位竞争者存在)。
中国人民当年自己搞两弹一星,付出了艰苦卓绝的努力;但是 1999 年直接花钱从乌克兰买来一艘完成度为 68% 的瓦良格号,后经过 13 年时间改造成为辽宁号航母,但这也比零基础从头制造一艘航母要快很多。
### 2.6.2 过于乐观自信,严重超期
年轻的程序员一般都比较乐观,而且表现在表面上,比如“您放心,这件事我两天搞定!”,结果经历了停电、死机、重新安装系统和工具软件、一个 Bug 找了 2 个小时(结果是因为把“=”写成了“==”)、由于 API 技术文档参数顺序写反了而导致的结果不对......等等挫折,最后花了 5 天的时间才搞定。
同样,即便都是有经验的程序员组成的团队也是如此,软件开发会存在比如节假日休假,员工请假,成员内部配合默契不够好,进展方向错误等等一系列类似于上文事例中的现实因素,阻碍着我们项目的完成,延误项目完成日期。
这个现象在心理学上,称之为规划谬误,规划谬误这一概念是由诺贝尔经济学奖获得者,著名心理学家 Kahneman 和 Tversky1979首次提出的。
规划谬误是指人们在估计未来任务的完成时间时,,倾向于过度乐观,低估任务完成时间的一种现象。规划谬误的心理机制主要包括规划谬误理论和记忆偏差理论。规划谬误的影响因素主要有认知因素、动机因素、个体的经验水平、目标任务的性质等。
其实不只是我们个人,许多大的工程,也存在这样的规划谬误的问题:
- 悉尼歌剧院的建设就是一个说明这一谬论的著名例子。它最初估计于1963年完成耗资700万美元但该项目最终在预期日期后的10年内完成且耗资1.02亿美元。
- 埃及博物馆新馆2002 年立项2012 年动工,预计 2015 年竣工。结果由于施工难度大、造价超预算等多方面原因,延迟到 2019 年;但是新冠疫情袭来,再次推迟到 2021 年;然后,埃及内乱,推迟到 2023 年春天。
所以,我们在估计项目的完成时间的时候,不应该以一种理想的非常顺利的想法来预测项目的进程,应当多考虑能够影响项目进程的因素,并参考历史经验。一般情况下,如果按照最顺利的情况估算出的时间,再 $\times 2$ 或 $\times 3$ 得到的时间,会和实际的花费时间差不多。
### 2.6.3 过于谨慎周全,动手太晚
与 2.6.2 相反,有些生性谨慎的程序员会花较长的时间学习、比较各种技术方案的优缺点,结果因为要解决一个小问题,扯出来一大堆不相干的问题。秀才造反,三年不成。
在工作中,正确的学习方法,应该是针对问题的强指向性学习,而不是像在学校中那样的打基础性质的范范的学习。比如,应该先确定要解决的问题本身作为努力的目标,再进行有针对性的学习,并且要动手进行验证,尽早 make your hands dirty把手弄脏获得第一手经验。
### 2.6.4 依赖链条过长,不分重点
一个真实的例子是这样的:当时木头刚刚换岗位,老板让先熟悉一下工作环境,于是笔者想学习一下如何使用 PyTorch 训练一个简单的神经网络模型。
1. 看 PyTorch 文档,发现提到了 GPU以前没接触过觉得很有趣
2. 去 NAVIDIA 网站看 GPU 的相关知识,太多内容了,绕在里面出不来了;
3. 要装 GPU 显卡驱动,不知道自己的显卡是什么型号,于是又搜索了一大堆资料,装错了好几回,不得不重装操作系统;
4. 然后又要装 CUDA 驱动但是安装哪个版本呢NAVIDIA 那个版本对照文档太烂了,木头一边骂选项太多,一边逐个排查;
5. 终于该装 PyTorch 了,发现与 CUDA 驱动版本对不上,还要降低一个版本才行;
6. 装好 PyTorch 后,从例子中找了一个神经网络的例子,用 GPU 几秒钟就训练完毕了,心里非常得意;
7. 然后用 CPU 又训练了一遍,想证明自己前面花的时间是值得的,结果用 CPU 训练只花了 10 几秒!
这让木头很尴尬:针对自己想训练一个简单的神经网络的目标来说,前面的努力显然是白费了。当然,这些知识以后在使用 GPU 时还是能用得上的,只是在当前这个阶段花这一周的时间做了些没啥大用的事还是有些心疼的,因为还有更重要的事情要做。
### 2.6.5 过早优化方案,改了又改
这个例子也是木头亲历的,在第五章中还会提到,这里先简单说一下。
使用 PyTorch 做大规模神经网络的分布式训练时,要每隔一段时间就保存一次训练结果,避免由于特殊原因导致在训练了一周后突然宕机而一无所获。但是,系统本地磁盘容量有限,而且一旦宕机,所有虚拟机将会被重置,保存的结果也会丢失。而保存训练结果到远程的 Azure 磁盘上又相当地耗费时间。
于是设计人员想到了三层解决方案:
1. 把训练中间结果从 GPU 中拷贝到 CPU 内存中,这个过程只需要花费毫秒级的时间;
2. 把内存中的数据再拷贝到本地硬盘中,这个过程需要花费几秒的时间;
3. 从本地硬盘再挪到云存储中,这个过程需要花费十几分钟的时间。
<img src="img/Slide19.SVG"/>
图 2.6.2 分布式神经网络训练中的硬件容错优化
以上过程2、3是异步的实际的等待时间只是第一步所以相当于成千万倍地节省了保存中间结果的时间。
但是,设计人员想优化系统,于是在多个 Pod 的本地存储之间增加了一层复制机制,目的是在某个 Pod 宕机而新的 Pod 填补上来后,可以利用在其它 Pod 上的复制数据快速地恢复新 Pod 上的状态。
这听起来是一个非常完美的优化方案!但是问题也就出在这里:
1. 两个 Pod 之间的复制需要策略;
2. 复制时需要在 InfiniBand网络硬件上使用 C++ 进行特殊编程,而其它代码都是用 Python 写的;
3. 复制时需要占用网络带宽;
4. 复制可能存在失败的情况,要处理;
5. 本地存储要和云存储有正确的版本对应关系。
这就导致了第二层的优化设计带来了很多麻烦,需要花费很长的时间才能搞定。而且,最重要的是,经过统计使用记录后发现,第二层的恢复机制被使用的概率极小,而从第三层进行恢复花费不了很长的时间,相比于某个 Pod 宕机再恢复所花的时间可以忽略不计。
### 2.6.6 过早泛化方案,样本不足
这里有一个正例和一个反例,我们先说正例吧。
#### 正例:必应搜索中的 Instant Answer
所谓 Instant Answer就是一种搜索结果与普通的只有“一个标题+一个URL+一段简短的内容片段”组成的搜索结果不同。如图 2.6.3 所示。
<img src="img/Slide20.SVG"/>
图 2.6.3 必应搜索结果中的 Instant Answer
仔细分析这三个 Answer 的外观,它们基本上由几个部分组成:
1. 一张图片;
2. 一段简介;
3. 一个 URL
4. 几个描述字段(左边那个没有);
5. 电视剧多出一些“季”和“集”的选择。
所以,完全可以用一种可配置的界面设计来统一这些 Answer 的展示。
从 Answer 的 Trigger触发词情况来看基本上都是“实体+关键字”的形式“实体”就是“汽车”、“生活大爆炸”、“流浪地球”等词关键字可以是“在线观看”、“电视剧”、“电影”、“视频”等等可以有明显搜索意向intent的词汇。
在美国的搜索团队中,每个 Domain领域比如汽车、电视剧、电影的 Answer 都是由一个专门的团队来负责。但是,笔者和一些同事一起研究了一下,觉得完全可以用同一套 Pipeline 来生成 Answer包括源数据加工、关键词提取、搜索触发逻辑、用户界面展示等等。而老板也同意我们的看法但是要求我们先做 7 个不同 Domain 的 Answer 后,再回过头来泛化这个 Pipeline。
为什么是 7 个?而是不是 3、5、8也没有严格的理论可以借鉴只不过根据 Answer 的多样化情况来看“7”是一个比较合适的数字少一些的话怕有情况遇不到多一些的话会有重复但其实“5”也是可以的再少就不行了。
最后泛化的结果是,我们用同一个 Pipeline 通过泛化做了 200+ 个 Answer让美国的同行目瞪口呆。
#### 反例:多智能体强化学习优化平台
下面我们说一个反例,这个例子在第五章还会讲到。
研究员们在完成了一个多智能体强化学习的项目后,成功地解决了远洋空集装箱调配的问题,于是想把它做成一个平台,供有类似应用场景的用户使用。
但是面临的问题是:
1. 强化学习本身热度不够,知道的人不多;
2. 入门门槛较高,数据采集困难;
3. 如果奖励设计不合理,训练时算法不容易收敛;
4. 实际应用场景各不相同,如果是另外一个远洋运输公司倒是可以直接使用,但是换成一个物流公司,就需要修改或二次开发后才能使用,没有任何用户具备这样的实力,而具备这样实力的研究者也不会使用这个平台。
所以,这是一个典型的泛化失败的案例。
### 2.6.7 全栈工程师梦,多不如精
#### 全栈工程师
全栈工程师是指掌握多种软件开发技能,并能利用这些技能独立完成产品的人。
图 2.6.4 右侧的树状结构是一个全栈工程师要掌握的技术的示意图。
<img src="img/Slide21.SVG"/>
图 2.6.4 全栈工程师与全流程工程师
稍微努力一些的软件工程师6 个月可以基本掌握一门开发语言或者一种开发工具或者是一个开发框架,那么我们可以大致计算一下成为全栈工程师的时间:
- Web 前端假设需要会两种主流框架Vue.js, React则需要 1 年的时间掌握;
- 移动前端,假设需要会 iOS 和 Android 的开发,则需要 1 年的时间掌握;
- 胖客户端,假设需要会 Java 的 Eclipse 和 .Net 的 C#,需要 1 年的时间;
- 中间件、分布式等等,假设需要掌握 Java 的 Tomcat 和 ActiveMQ需要 1 年时间;
- 后台开发,假设需要掌握网络通信和分布式容灾或扩容两种基本技术,需要 1 年的时间;
- 数据库,假设需要掌握 MySQL 和 MongoDB 两种,需要 1 年的时间。
当然,上面的时间都是粗略估计的,有些东西可能需要 1 个月或更短的时间即可掌握,那么成为全栈工程师需要 5~6 年的时间。看上去时间不长,但是,作为一个工薪阶层,哪里会有这么长的学习时间来掌握这些技能?
- 有些读者也许会说:“我可以在工作中边干边学!” 当然可以,但是哪个公司会有那么巧的机遇可以接触到各个层面去学习各种技术?
- 还有些人会说:“我业余时间自己学!” 也挺好!但是自学时一般不会遇到复杂的应用场景,相当于“单元测试覆盖率不足”,那么也就达不到“掌握”的目的。
另外,上面只是在说“掌握”而非“精通”。笔者的一个朋友说:“全栈工程师,就是一些创业公司搞出来的噱头,给你发一份工资当几个人用。就像我们 xx 项目成立之初,我作为一个 C++ 程序员开始搞 php、html5、css3、vue.js、uniapp、flutter甚至自己用 PSPhotoShop做海报做轮播图做 logo......都是只会一点,不能称之为精通,已完成任务为目的,有点不求甚解的意思。你可以去招聘网站上看看招全栈的几乎都是创业公司!”
假设有全栈工程师的存在,其优点是显而易见的:减少了沟通时间,降低沟通成本,提高开发效率。一个人搞定一切,觉得前面有些代码影响了后面的开发,他随手就可以改掉。所有的逻辑都烂熟于心,排查 Bug 时非常容易。
**但是,全栈工程师的真正意义在于团队合作中,他可以有全局性思维,可以带领团队走最短路径,而不是一个人负责开发所有代码。**
#### 全流程工程师
其实,阻碍软件产品顺利发布的主要困难并非所采用的技术本身,而是如何利用软件工程知识把用户需求准确、快速地转换成为高质量的代码。学习一门技术不难,掌握产品转换的技巧才是关键。前者是“死的”,后者是“活的”。
在图 2.6.4 中的左侧,还列出了一些词,如:“需求、分发、设计、开发、测试、管理、运维、部署”等等,它们并不是针对右侧的特定技术层面而所需要的技能,而是在软件工程中的各个环节中所需要完成的“技术动作”。根据不同的用户需求,合理地使用这些“技术动作”,就可以成为“全流程工程师”,这也是本书的写作目的。
### 2.6.8 三十岁做管理,中年危机
#### 保持热情
一般来说女性成熟得较早,而男性在三四十岁的时候,刚好是正值当打之年,可以大展宏图。
笔者在微软美国总部出差的时候,见过很多白胡子大叔仍然激情四射地在写代码。这些人一直是属于生龙活虎的人,一直保持着对工作和生活的热情,一直在追逐自己的兴趣爱好,一直在处理一些比较有挑战的工作,这样就不会觉得自己会步入中年,感觉还很年轻,自然不会有危机感。
#### 保持积累
笔者以前的一位在微软的领导,针对一些年轻人不断跳槽想尽快提高收入的现象,曾经这样说过:“让你得到财富的正确方法是积累,是每个月有稳定的收入汇入你的银行账户,而不是靠一夜暴富。”
在年轻的时候努力,有一些积累到后面就不会觉得很困难,而随着经验的积累也会厚积薄发。没钱买房子还可以靠银行贷款,知识储备可是没有“预支”的说法,不积累只能“透支”。
#### 保持好奇
要有新的追求的目标,学习新的知识,不吃老本儿,既可以让自己感觉到新鲜,也能够及时充电,也不会有什么危机感。
笔者到研究院工作之前,确实觉得继续在工程院工作已经有天花板的感觉了,好像没有什么可以突破的,既没有目标,也没有动力,更没有方法。到了研究院后接触了人工智能的知识,像是打开了一扇天窗,好奇心爆棚,利用一切时间贪婪地学习新知识。等再次回到工程院工作时,这些新知识又可以有用武之地。

Просмотреть файл

@ -0,0 +1,6 @@
## 2.7 练习
找出程序中运行效率最低的代码并修改后使之提高性能。
split函数

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 54 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 50 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 156 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 68 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 106 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 53 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 123 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 53 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 143 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 57 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 144 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 58 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 96 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 58 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 113 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 70 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 147 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 75 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 100 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 50 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 100 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 68 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 88 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 43 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 216 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 89 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 84 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 318 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 100 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 109 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 98 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 332 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 61 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 116 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 117 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 664 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 102 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 82 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 142 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 40 KiB

Просмотреть файл

@ -1,18 +1,26 @@
<img src="img/Slide1.JPG"/>
<img src="img/Slide1.SVG"/>
(插入一些说明性文字,重点在介绍上下文,串连)
上一章我们讲的是专业能力,具备了那些专业能力就可以成为一个合格的软件工程师。但是,如果想往更高的地方走,就需要本章中所讲的认知能力的辅助。
<img src="img/Slide2.JPG"/>
在笔者看来,认知能力包括:
- 沟通能力
- 学习能力
- 解决问题的能力
- 系统化思维能力
<img src="img/Slide2.SVG"/>
### 参考资料
https://www.freecodecamp.org/news/how-to-think-like-a-programmer-lessons-in-problem-solving-d1d8bf1de7d2/
- https://www.freecodecamp.org/news/how-to-think-like-a-programmer-lessons-in-problem-solving-d1d8bf1de7d2/
https://www.jianshu.com/p/0f46896ab4a0
- 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

Просмотреть файл

@ -1,7 +1,7 @@
## 3.1 沟通能力
### 3.1.1 培养基本的沟通能力
### 3.1.1 沟通的重要性
Nobody is an island. 没有人是一座孤岛。
@ -15,6 +15,10 @@ Nobody is an island. 没有人是一座孤岛。
- 和老板的沟通
- 和客户的沟通
<img src="img/Slide3.SVG"/>
图 3.1.1 工作中的沟通
如果按照形式分类,又可以分为:
- 正式沟通与非正式沟通
@ -24,23 +28,17 @@ Nobody is an island. 没有人是一座孤岛。
- 内部沟通和外部沟通
- 单独沟通和集体沟通
如果按信息内容和目的分类,可以是:
- 基本的信息沟通
- 工作中的职业沟通
- 高级的情感沟通
一个不想沟通又不会沟通的人,很难融入到团队中与他人合作完成项目。所以,沟通,已经成为在职场中生存的基本手段了。
沟通是双向的,是一个编码、解码的过程,要求你既会说又会听。笔者认为不存在单向沟通,因为那不叫作沟通,叫做信息发布。
### 3.1.2 沟通的最佳实践
<img src="img/Slide3.JPG"/>
<img src="img/Slide4.SVG"/>
图 3.1.1 沟通的最佳实践
图 3.1.2 沟通的最佳实践
#### 表达深思熟虑后的观点
#### 1. 表达深思熟虑后的观点
表达观点时,要有理有据(虽然不能保证合情合理),不能道听途说地只说个结论,没有推理过程或者解释说明。
@ -60,17 +58,17 @@ Nobody is an island. 没有人是一座孤岛。
乐队里有一位 C自认为自己多弹了几年吉他有一些演出经验经常会长篇大论地写一些东西搬出来一些不明觉厉的名词最后总不忘加一句“这些都是我上学时就玩儿剩下的”。木头只好说“大家看看老 C 的文字,观点完整、有理有据,请大家学习。” 确实在“观点完整”上C 确实做到了。有人私下问木头这件事,木头回答说:“我说观点完整,并没有说观点正确,我说有理有据,没有说合情合理。”
#### 不要用反问句
#### 2. 谨慎使用反问句
完整地表达观点,是一种思考成熟、具有知识体系的表现。微信的出现其实是为了普通大众服务的,往往是三言两语说完就走,因为不具备完整表达观点的能力。
还有些人,可能是在中学就养成的坏毛病,总是反问别人。比如大家在邻居微信群中担忧疫情防控放开的问题,有个年轻人就说:“你得过感冒吗?” 言下之意就是新冠病毒和感冒的危害一样轻,但后来的事实证明要严重很多,恨不得是两三种感冒加起来那么严重。这个年轻人后来在群里求药,但是没有人原意搭理他。
笔者看着他的反问句不舒服,就回答说:“年轻人可能还容易恢复,但是老年人就比较麻烦。” 没想到又有一个年轻人跳出来反问笔者:“你亲身经历过吗?” 言下之意是“不要听舆论的宣传,老年人没问题的”。笔者当时就以其人之道还治其人之身反问他:“你是老人吗?” 意思是不是老人就没有同理心,不会站在其它的人的立场上思考。
笔者看着他的反问句不舒服,就回答说:“年轻人可能还容易恢复,但是老年人就比较麻烦。” 没想到又有一个年轻人跳出来反问笔者:“你亲身经历过吗?” 言下之意是“不要听舆论的宣传,老年人没问题的”。笔者当时就以其人之道还治其人之身反问他:“你是老人吗?” 意思是“你不是老人就没有同理心,不会站在其它的人的立场上思考
但是,完整地表达观点经常会吃亏,因为言多必失,大概率会有漏洞。有些人就会抓住其中一个小漏洞,或者是一个语病、一个词汇来反驳。乐队里就有这么一个家伙,总是不好好说话,阴阳怪气的总用反问句,比如“这怎么会是性别问题?”、“你觉得这样做就是公平的吗?”,这些看似普通的反问句在上下文里的伤害极大,使得大家不能正常交流,最后被木头踢出了乐队群。
#### 认清“角度”与“高度”
#### 3. 认清“角度”与“高度”
在人类所在的三维世界中,当然有“角度”的概念,同样看一个物理存在的巨大的物体,有的只能看到它的左侧,有的人只能看到右侧,由此会引申到对待一个问题的看法,不同的人会有不同的“角度”。
@ -82,7 +80,7 @@ Nobody is an island. 没有人是一座孤岛。
你自认为从 360 度观察到了事务的本质,但是领导却是从 720 度(包括上下两个维度)做了更多的思考。所以,说“角度”这个词,只是给你一个面子,其实是“高度”的差别。
#### 基于事实的讨论,而非立场
#### 4. 基于事实的讨论,而非立场
- 利益:隐藏起来的真正的需求。
@ -100,7 +98,7 @@ Nobody is an island. 没有人是一座孤岛。
很典型的情况是,面对一个关键技术问题,两个人各持己见互不相让,其背后的原因很可能是采用了谁的建议,谁就会在 promotion 的路上向前迈进了一步。有个实际的例子,木头在 Windows 组时,常听到很远的隔壁的两个同事 A 和 B 因为在 Edge 浏览器上做银行插件时究竟应该采用哪种技术方案而进行讨论A 是一个 Senior DevB 是一个 SDE II。后来 B 得到了 promotion 到 Senior 级别在邮件通告中的罗列的一条理由就是B 在该项目上贡献突出,在技术方案的选择上与同组的一名 Senior 级别的员工竞争而胜出。
#### 简洁不发散
#### 5. 简洁不发散
沟通时,每个观点完整是必须的,但是在其它方面要简洁吗,不要过于发散。
@ -108,7 +106,7 @@ Nobody is an island. 没有人是一座孤岛。
但是有一些人又过于简洁,茶壶煮饺子,心里有话但是倒不出来。笔者听说有个同事在 Machine Learning 上很有功底,就跑去请教,结果对方说了一些不是关键点的信息,听得云里雾里的。可能在对方看来,“有些基本的信息我都不用说你自然应该明白”,于是直接进入了细枝末节。
#### 婉转表达否定
#### 6. 婉转表达否定
假设你和领导进行 1:1 的年终总结谈话,领导说:“你在这个项目里承担了一些重要的工作,技术能力很不错,但是在与同事进行技术讨论时,在说话技巧上还有一些进步的空间。”
@ -116,7 +114,7 @@ Nobody is an island. 没有人是一座孤岛。
在《星际迷航》电影里经常会看到这样的对话船长说“把动力系统全部移到船头进行形成能量网保护”操作员可能会说“Negative不行我们需要至少10%的能量储备用于随时做光速跃迁逃逸。”,用 Positive/Negative 就会比较客观婉转,给船长留了面子。
#### 注意语气语调
#### 7. 注意语气语调
俗话说“有理不在声高”。有些人说话的音量很大,像是在吵架;有些人语速特别快,通常需要听者在脑子里把话在重复一遍才能明白;还有些人语气比较强硬,不太会用词。
@ -126,13 +124,13 @@ Nobody is an island. 没有人是一座孤岛。
2. 速度慢,还稍微有些结巴(当然这不是优点),不过反而能让人明白他在说什么。
3. 不和别人争吵,有不同意见时,他表达完自己的观点后,如果对方不同意,他就会说“行,那再回去研究研究吧”,这样不管最终谁对谁错,都给双方留了余地。
#### “一会儿回复您”
#### 8. “一会儿回复您”
如果需要较长时间的思考,也可以回复说“让我先想想,一会儿回复您”。
曾经有一位朋友(微软中国 ARD 的韦青老师)请笔者去给一个合资公司讲讲“微软的工程师文化”,因为笔者当时很忙,一时不能确定能不能讲好,或者是需要多长时间的准备,所以就在第一时间回复说“让我想想”。两个小时后,给予了对方肯定的答复,然后就在业余时间开始准备演讲内容,大部分内容都是本书中的实践中的软件工程,最后的演讲效果非常好,这才启发、激励笔者继续写完这本书,相信会得到很好的读者反馈。
#### 面对面的讨论更加有效,慵懒的文字会产生误解
#### 9. 面对面的讨论更加有效,慵懒的文字会产生误解
以前在办公室里听到打字速度很快(而且还大胆地使用了机械键盘)时,就知道这个家伙一定在用电脑微信聊天,因为写代码的速度不可能那么快。现在面对疫情,大家都采用了线上办公,每天进行大量的文字交流。有的人文字表达能力非常差,而且懒,自己头脑中是有上下文信息的,但是不在文字中表达出来,往往造成对方误会。
@ -140,7 +138,7 @@ Nobody is an island. 没有人是一座孤岛。
还有一个特点是,一般的实习生在写字时都会带上一个“啊”字,比如:“是啊”、“我也不知道啊”、“就是那样啊”,听上去像吵架。因为“啊”字本身在说出来时是一个轻声的后缀,没有实际含义,但是写出来就变成了一个强调的语气词,看上去很不舒服。
#### 少用对抗思维,多用平行思维
#### 10. 少用对抗思维,多用平行思维
同事之间,如果没有上述的立场问题作怪,就尽量“先扬后抑”,或者“多扬少抑”。
@ -150,7 +148,7 @@ Nobody is an island. 没有人是一座孤岛。
这种技巧,是 B 先给了 A 一个较强的心理暗示:咱俩是一个阵营的。这样 A 就会表现出合作的态度。
#### 说话不要绕弯子
#### 11. 说话不要绕弯子
比如,有个同事建议:“到了年底,因为美国那边要休圣诞节假期,所以我们不如等他们都休假回来后再一起讨论后续的安排。” 其实是这个同事的年假没用完,他想在 12 月底休两周的假,他不直说,却把美国人搬出来当挡箭牌。
@ -158,7 +156,7 @@ Nobody is an island. 没有人是一座孤岛。
这听上去就是很为演出效果考虑的感觉,但是这一个改变就要到春节后再开音乐会了,排练不好安排。员工们过完春节刚刚来上班,你来个“马后炮”,不论是观众和乐手,心气儿都差远了。木头看出来了是因为他们的乐手凑不齐,所以拒绝了这个队长的请求,说:你如果缺乐手可以向别的乐队借,没必要把自己乐队的困难绕个弯子转嫁到整个演出上。
#### 相同的话不要重复说
#### 12. 相同的话不要重复说
在工程师层面的沟通,不需要像在大街上聊天似的,为了增加亲密程度和聊天长度而说“车轱辘话”。车轱辘话出现的原因是:
@ -167,7 +165,7 @@ Nobody is an island. 没有人是一座孤岛。
一旦出现车轱辘话,在说者看来好像是强调了刚才的观点,但是在听者看来会得到两个结论:这个人固执;他没别的理由了。这与说者想达到的目的正好相反。
#### 不要乱用“沉默”的权力
#### 13. 不要乱用“沉默”的权力
笔者在写本书的“用户与需求”部分时,曾经想要求一位以前共过事的 PM 一起写,就发了一封邀请邮件,但是却石沉大海,也不好再追说,干脆自己写了。笔者感到很不可思议的是,曾经和那位 PM 在项目最艰难的时刻共同努力,最终令项目得到了总部的认可,相当于一起“扛过枪、负过伤”的交情,为什么对方会沉默呢?
@ -175,7 +173,7 @@ Nobody is an island. 没有人是一座孤岛。
同样的问题经常发生在同事或朋友之间的微信通信上,有的时候甚至一句“新年快乐”发过去却得不到半点儿回音。笔者只是在对对方的行为或言语极为反感时,才会采用“沉默”这种手段。所以奉劝那些容易忘记回复消息的读者们,真正地把对方放在心上(这样对方才能把你也放在心上),在方便的时候第一时间回复对方。
#### 不抱怨结果,要分析原因
#### 14. 不抱怨结果,要分析原因
无效的沟通往往是从对糟糕的结果的抱怨开始的。
@ -183,7 +181,7 @@ Nobody is an island. 没有人是一座孤岛。
因为家长自身处于强势地位,不太注重沟通的方式。但是一般的公司领导会很注意这些细节,在上面那种情况下一般会说:“这次考试(项目)结果不太理想,应该还可以做得更好,你有没有自己分析过是什么原因造成的呢?” 这样拉开话匣子,会让对方可以接受。
#### 不挑战别人的决定,而是提出建设性意见
#### 15. 不挑战别人的决定,而是提出建设性意见
比起上一条来,更进一步。
@ -192,3 +190,49 @@ Nobody is an island. 没有人是一座孤岛。
如果是同级别的人谈话,对方的意思往往是“我有更好的方案”,但是他不直接说,而是以问句开始,这就容易拱火儿。如果是不同级别的人,劝你还是最好不这样问话,因为领导掌握的信息比你多,做出的决策也会更合理,让领导解释理由是很不礼貌的,这相当于是一种挑战。
不论哪种场合,如果直接了当地把自己的“具有建设性”的意见说出来,会得到领导的赏识和同事的赞许。“建设性”这个词还是木头在学习桥牌时第一次遇到的,叫做“建设性应叫”,意思是对方表达了完整的观点后,我应该在尊重对方观点的前提下,提出自己的一些局部或不同方向的补充,来共同完善这个观点。
### 3.1.3 沟通能力的培养
沟通的前提是你要有输出,别人才能理解你,才能达到沟通的目的;你也要有输入,才能正确地理解别人。一般人都可以做到输入(听),但是能力欠缺的人没有输出或者很少有输出,造成沟通障碍,据笔者观察,在一个团队中,这类人占比为 10%-20%,虽然他们不会影响整个团队的协作,但是却会影响个人的职业发展。
如果想提高输出的能力,从下面三点入手即可:
- 基本的信息沟通
- 工作中的职业沟通
- 高级的情感沟通
#### 1. 基本的信息沟通
【最佳实践】
- 工作餐尽量和大家一起吃,有说有笑。
- 不知道该说什么的时候,可以先听听大家说什么,然后就可以确定自己的话题是不是会得到响应。
- 可以先指定一个人,比如:“老李,你上次说买了个国产车,质量行吗?我最近也想每一辆。” 对方肯定会打开话匣子给你分享经验。
- 可以讲一些趣事或笑话,但不是从网上趸来的,而是自己亲身经历的。
- 就一个新闻或一个事件发表自己的简单看法比如“NAVIDIA 不能在中国卖 GPU对它自己的利润有很多影响中国是世界上最多使用 GPU 的国家。”
#### 2. 工作中的职业沟通
【最佳实践】
- 遇到疑难问题时,主动寻求他人的帮助。当问题较为严重时,寻求老板的帮助。
- 主动帮助他人,分享你的经验。
- 开会时主动发言,发表自己的看法。
- 主动承担任务池中的工作项,并努力完成,及时交付。
- 和 PM 搞好关系,耐心解答技术问题。
- 与外部团队合作时,态度要谦虚谨慎。
- 及时反馈,无论是答应了谁做什么事,都要及时反馈,不能等着别人来问你进度。
#### 3. 高级的情感沟通
即“情商”。
【最佳实践】
- 逢年过节给亲朋好友领导同事拜年,如果有人主动给你拜年,那么下次你要抢先一步回馈。
- 发了朋友圈收了赞和评论,记得回复朋友们的评论,也记得给朋友们的朋友圈点赞。
- 关心一下他人的遭遇,比如“上次你骑车摔倒了,没伤到骨头吧?”
- 收到别人的红包,要发一个快乐的表情表示感谢,但实际上你可能只抢到了 2.46 元,而别人都是好几十块钱。此时你可以炫耀地说:“看,二四六多吉利,好事成双!”
- 多参加团队活动,或者是社会团体活动,比如乐队、读书会、羽毛球俱乐部等等,认识工作以外的人。
- 分享自己最近读过的好书、看过的好影视剧,并附加自己的正面评论。

Просмотреть файл

@ -1,11 +1,11 @@
## 3.4 学习能力与方法
## 3.4 学习能力
### 3.4.1 元能力
**学习能力**是一项元能力。元能力,就是提升其它能力的能力。而学习能力所学习的目标是**知识**和**技能**。
<img src="img/Slide16.JPG"/>
<img src="img/Slide5.SVG"/>
图 3.4.1 能力
@ -42,14 +42,14 @@ $$
但是很多理工科的专业的学生或者毕业后从事科学研究的人他们需要的不是记忆力而是创造力而那些测试题是阻碍这些人受到良好教育的绊脚石。于是布鲁姆提出了一个新的学习教育分类法用于归类不同学习程度的认知框架。2000 年,他的学生 Lorin Anderson 修订过一些内容,这就是影响了两代美国人的“认知目标分类体系”。
<img src="img/Slide17.JPG"/>
<img src="img/Slide6.SVG"/>
图 3.4.2 布鲁姆分类
布鲁姆是根据人的“认知过程从简单到复杂,由具体到抽象”这一规律来作为其教育目标分类理论依据的。教育目标分类强调指导教学过程和对结果进行评价,用来判断学生对一个知识点的精通程度,从低层次的“记忆、理解、应用”,到高层次的“分析、评价、创造”。
#### 第1层 - 记忆Remember
#### 1. 记忆Remember
死记硬背,照本宣科。
@ -69,7 +69,7 @@ $$
这也是一个刚毕业的学生需要达到的基本技能。
#### 第2层 - 理解Understand
#### 2. 理解Understand
分星擘两,融会贯通。
@ -91,7 +91,7 @@ $$
以上这些都是软件工程师的日常行为,它要求必须理解算法、代码、结构、系统、协议等等,才能正确地工作。在可以自己独立写代码之前,先学习一下别人的代码,深刻理解。
#### 第3层 - 应用Apply
#### 3. 应用Apply
举一反三,熟能生巧。
@ -106,7 +106,7 @@ $$
学到的一些技术,也通过简单的测试程序理解了其工作原理,但是能够正确地应用到实际项目中,还是需要一些努力的。这是软件工程师能够独立工作的前提。
#### 第4层 - 分析Analyze
#### 4. 分析Analyze
抽丝剥茧,阐幽显微。
@ -123,7 +123,7 @@ $$
听完以上的一系列分析后,新手们会得到 What, Why, How, When 等重要信息,从而可以立刻开始工作,而那位有经验的 mentor 就可以去喝杯便宜的速溶咖啡并和朋友聊聊股票行情了,毕竟他被套牢了一大笔资金,如果被老婆发现可是不得了。
#### 第5层 - 评价Evaluation
#### 5. 评价Evaluation
拨云见日,玉尺量才。
@ -141,7 +141,7 @@ $$
评价的能力是日积月累练就的。作为一名新手,当领导征询你对一件事情的意见时,最好不要给出一些片面的、主观的评论,而应该用一种谦虚的态度在局部上补充一些细节。
#### 第6层 - 创造Create
#### 6. 创造Create
独具匠心,别开生面。
@ -165,7 +165,7 @@ $$
3. 过程知识
4. 元认知知识
<img src="img/Slide18.JPG"/>
<img src="img/Slide7.SVG"/>
图 3.4.3 知识的难度
@ -234,7 +234,7 @@ $$
3.4.2 小节和 3.4.3 小节是两个不同维度的的分类或分层,那么当这两个维度组合在一起,会发生什么事情呢?
<img src="img/Slide19.JPG"/>
<img src="img/Slide8.SVG"/>
图 3.4.4 二维知识/学习分类
@ -257,53 +257,3 @@ $$
有了表 3.4.1 的指导,我们可以准确地判断一个具体问题所处的层次、难度,也可以判断自己的能力所在的层次、难度。
### 3.4.5 学习方法
#### 1. 费曼学习法
这个学习方法是诺奖获得者费曼提出来,然后由后人总结发展出来的。其核心就是先阅读大量资料,然后找出其中的知识,再把这个知识用自己的方式讲给一个完全不懂的人。
在微软的团队中,一般老板会组织大家进行技术交流,无论是与工作相关的还是无关的都可以。每个人根据自己的兴趣爱好在业余时间学习的技术知识,然后把它们组织成 PPT 形式,在每周的开发人员组会时(不是 Scrum Meeting讲给大家听时间在半小时左右每周一人。大家可以任意打断演讲而提出问题。
另外一个极端的例子是小黄鸭调试法:程序员总是在桌子上放橡皮一只小黄鸭,在调试代码的时候详细地向鸭子解释每行代码。如果没有小黄鸭玩具,找一个同事临时充当也行。你会发现在讲解的过程中,可以突然发现一些隐藏的问题,从而帮助你快速解决 Bug。其原理是你如果只是盯着代码看大脑会忽略一些重要细节而当你试图讲出来时为了让对方听明白就会揪出这些细节来。从而发现问题。
#### 2. SQ3R 阅读法
SQ3R 代表着五个单词:
1. Survey浏览浏览学习内容。比如拿到《智能之门》后先看章节目录第四章是单变量线性回归。
2. Question提问对一些知识点提出初步的问题。比如训练数据长得是什么样子回归的数学模型是什么公式最小二乘的数学原理是什么梯度下降的公式是如何得到的又是如何变成代码执行的
3. Read阅读带着问题深入阅读并找到答案。
4. Recite复述把书合上或者只看标题来默写最关键的梯度下降公式推导并写代码实现。
5. Review复习过几天后重复 4看看是不是能记住。
#### 3. 西蒙学习法
这是诺贝尔经济学奖获得者西蒙教授提出来的。其理论基础是:
1. 一门学问大概有 5 万个信息块(知识点);
2. 一个人记忆remember一个信息块需要 90 秒;
3. 5 万个信息块需要 1250 个小时;
4. 一周学习时间为 35 个小时,复习 5 个小时;
5. 1250 小时 / 35 小时 = 36 周 = 9 个月。
原理论中:
- 5 万块需要 1000 小时,这与 50000 x 90 秒 / 3600 秒 = 1250 小时相差太多,需要精确一些。
- 每周学习时间为 40 小时,但笔者认为不复习 5 个小时的话,会出现狗熊掰棒子的情况。
结论是:一个有一定基础的人,只要肯花时间下功夫,在最多 9 个月内可以掌握任何一门学问。
这听上去很疯狂,并且也没有定义“掌握”是如何定义的,但是笔者认为大学本科甚至研究生的课本,在 3 个月内就可以读完remember然后再花几个月理解understand并应用apply
#### 4. 思维导图学习法
这是英国人托尼·博赞发明的,他是世界记忆锦标赛和世界快速阅读锦标赛创始人,曾经帮助英国查尔斯王子提高记忆力,被称为记忆力之父。
标准的思维导图,是一个由中心向四周发散的层次逐级递减的图,可以认为是分类逐渐细化,如图 3.4.4 所示。
<img src="img/Slide20.JPG"/>
图 3.4.4 思维导图
其实,思维导图的方法和罗列多级列表的方法,在内容上没有任何区别,只不过思维导图具有特别的**形状、颜色、位置、关系连线**等信息,记忆时可以根据这些不同于纯文字的额外信息来辅助。另外,思维导图最好是**读者自己绘制**,这样对绘制的过程(也就是思考和归纳的过程)有很深刻的记忆。

Просмотреть файл

@ -1,16 +1,18 @@
## 3.2 解决问题的能力
关于“问题”这个词的定义有很多,在这里我们特指三类技术问题:
1. 要达到的目的,比如:用聚类算法处理数据、建立合理的拓扑结构、搭建模型预测趋势等等。
2. 要纠正的错误,比如:软件的输出和预期不一致、开发时间超过计划太多、用户量大时导致系统崩溃等等。
3. 要解决的疑问,比如:为什么在贪吃蛇游戏设计中应该使用链表、为什么很多程序员到了 30 岁就不愿意再写代码等等。
### 3.2.1 能力的评级
在前面的故事中提到过“解决问题的能力”,是指的一些简单的问题,只需要做出一两个正确的判断或者动作就可以解决。
解决问题的能力,需要五个阶段的培养或锻炼,下面我们采用倒序方法从能力高到能力低的顺序来讲述。
<img src="img/Slide4.JPG"/>
图 3.2.1 培养解决问题的能力
解决问题的能力高低可以有五级评价标准,下面我们采用倒序方法**从能力高到能力低**的顺序来讲述。
<img src="img/Slide9.SVG"/>
图 3.2.1 解决问题的能力评级
#### 阶段五:啥都不给
@ -26,7 +28,7 @@
但是有时候领导可能说得不太准确:木头同学,你需要在一个月的时间内,把所有中国重点城市的公交车的站点处理一下,后面才能写换乘算法。
<img src="img/Slide5.JPG"/>
<img src="img/Slide10.SVG"/>
图 3.2.2 公交站点的聚类
@ -65,7 +67,7 @@
但是,与公交站牌聚类的例子比较,可以看到二者的区别是:一个是在二维空间里的聚类,一个是在一维空间里的聚类,能保证聚类算法的效果是可信的吗?你需要做一些试验,来验证这一点。
<img src="img/Slide6.JPG"/>
<img src="img/Slide11.SVG"/>
图 3.2.3 人类性别聚类问题
@ -93,20 +95,18 @@
### 3.2.2 木头遇到的技术问题
#### 复现问题
软件工程师有一句话叫做“get your hands dirty”直译为“把手弄脏”引申为“亲自动手与尝试获得第一手资料”你只有切身复现与体会到一个问题的 pain point痛点才能深刻理解它这是解决一切问题的前提。
有一个用户给木头报了一个 bug在把 ONNX 模型从 32 位浮点精度转换成 16 位浮点精度的过程中,当使用单个样本做转换过程的测试时,很容易通过;但是当使用 32 个样本(作为一批)做测试时,基本上不能通过。因为转换过程会使用 GPU 以及内存资源,所以该用户猜测是多个样本带来了更多的资源占用,从而导致失败。
#### 1. 复现问题
木头拿到了用户的真实环境(模型、测试代码、样本)后,首先在自己的 GPU 环境中复现repro32 个样本果真会导致转换失败;然后又用 16 个、8 个、4 个、2 个样本做测试,最后得到的结果是只有 2 个或 1 个样本时,转换才会成功。
<img src="img/Slide7.JPG"/>
<img src="img/Slide12.SVG"/>
图 3.2.4 培养解决问题的能力
#### 排查疑点
#### 2. 排查疑点
其次检查样本的正确性,通过对比几个样本的字段,除了数值有差异外,没有别的不同,这就避免了字段个数不同或者有些字段为空值带来的插值误差。
@ -139,7 +139,9 @@ np.allclose(x, y, rtol=1e-2, atol=1e-3)
是不是因为在模型中有一些随机因素造成了推理结果不准确呢?于是,木头检查了一遍模型,并没有返现有 dropout 等算子(操作符)出现,所以排除了这种情况。
#### 定位原因
【最佳实践】产生一个问题的原因有很多种,可以认为是星形结构(如图 3.3.3把这些原因罗列出来一个个地去试验即可找到根本原因root cause
#### 3. 定位原因
如果只用一个样本,获得到什么结果呢?木头发现,在一个样本的情况下,转换程序在尝试过几次之后,可以完成模型转换,但是并不稳定。此时,如果把验证精度宽限到:
@ -170,16 +172,29 @@ np.allclose(x, y, rtol=1e-1, atol=1e-2)
```
两次的推理结果完全一致!
#### 解释现象
【最佳实践】采用对比法是一个相对简单有效的办法,而检查代码逻辑就复杂得多。
#### 4. 解释现象
这就说明确实是 GPU 在做推理运算时不稳定,每次的结果都会有一些精度上的误差。当使用一个样本做多次验证时,总会有一次和 32 位模型的数值精度相差不大,所以很容易通过;但是当使用 32 个样本时,虽然偏差较小,但是方差就比较大,很难同时满足 32 个样本的精度差都很小的情况,所以就不能通过验证。
#### 小结
【最佳实践】这一步很关键,要把我们认为的 root cause根本原因和该 Bug 所产生的现象联系起来,看看是否有因果关系。
在上面的过程中,木头经过了以下步骤来复现与理解问题:
#### 5. 解决问题
1. 复现问题
2. 排查疑点
最后如何 fix 这个 bug并不是木头所在的小组的职责而是由其它小组专门负责所以木头就在 GitHub Issues 里给那个小组开了一个 bug并告知了相关的 PM。
【最佳实践】如果是读者自己需要 Fix 这个 Bug那么还需要增加相应的单月测试代码避免再次发生。
#### 6. 小结
【最佳实践】
在上面的过程中,木头经过了以下步骤来复现与理解问题,如图 3.2.5 所示:
0. 熟悉环境,这是对一些来到新环境的陌生读者开说的。
1. 复现问题,可以联系用户,让他们提供实测环境。
2. 排查疑点,主要有:
- 样本数量问题
- 样本字段/值问题
- 资源占用问题
@ -187,85 +202,49 @@ np.allclose(x, y, rtol=1e-1, atol=1e-2)
- 数值精度问题
- 32位/16位模型精度问题
- CPU/GPU问题
3. 定位原因
4. 解释现象
3. 定位原因,确定某个疑点。
4. 解释现象,避免误判断。
5. 解决问题。
其中,在排查疑点的过程中,大量地使用了“对比法”来寻找差异,而差异往往就是问题之所在。
<img src="img/Slide13.SVG"/>
另外就是使用“分析法”,比如检查代码逻辑,通过日志看资源占用问题等。
图 3.2.5 纠正错误的基本步骤
最后如何 fix 这个 bug并不是木头所在的小组的职责而是由其它小组专门负责所以木头就在 GitHub Issues 里给那个小组开了一个 bug并告知了相关的 PM
这个步骤/过程可以作为框架应用于绝大多数问题。其中,在排查疑点的过程中,大量地使用了“对比法”来寻找差异,而差异往往就是问题之所在。另外就是使用“分析法”,比如检查代码逻辑,通过日志看资源占用问题等
### 3.2.3 一个非技术的例子
### 3.2.3 提高解决问题的能力
再举一个比较通俗的例子:木头在某个级别上很长时间不能得到晋升,如何解决这个问题呢?
#### 多学习,多实践
和解决上面的技术问题一样,我们需要排查疑点,也就是影响晋升的因素都有哪些
拥有更丰富的知识是解决一切问题的基本前提,最简单的比喻就是:如果想搬起更重的石头,就需要有更大的力气。所以,保持好奇,多学习各方面的知识,从容面对快速发展的计算机软硬件技术,对一个软件工程师来说非常重要
<img src="img/Slide8.JPG"/>
笔者在小时候也看动画片,但是更多的时间是在看《十万个为什么》,阅读了一套丛书二十多本,帮助笔者建立了基本的科学世界观,知道一切神奇的现象后面都有产生它的本质。
图 3.2.5 培养解决问题的能力
关于实践软件工程师有一句常说的话叫做“make your hands dirty”直译为“把手弄脏”引申为“亲自动手与尝试获得第一手资料”你只有切身复现与体会到一个问题的 pain point痛点才能深刻理解它这是解决一切问题的前提。
#### 分析静态结构信息
- 个人能力
个人能力是根本,这也是本章要阐述的重点。木头在这一方面还是很有自信的。
比如有面试官问:为什么井盖一般都是圆的?你可能会嗤之以鼻地反问到:那为什么房子都造成方形的呢?因为你可能会下意识地认为那就是一种习惯或者约定俗成而已,为什么非得要刨根问底儿呢?
- 团队规模
其实每一种自然现象都有背后的科学道理,每一种人文现象都有背后的社会学原理,我们需要观察它的上下文信息后,再对齐做出判断。
在一个只有五个人的团队里,晋升的难度取决于你的老板是否受你的老板的老板重视,如果是的话,你很容易晋升,否则就很难,那么尽早离开是最好的选择。木头曾经在这个问题上用了一年多的时间才领悟到。
井盖为什么是圆形的?
如果一个团队同一级别的人多,那么大家的竞争就会比较激烈,当然这种竞争不会直接表现出来,而是在老板那里做平衡,最常见的情况就是“风水轮流转,今年到我家”
很多人会从圆形本身去思考,比如:容易制造、容易搬运、没有尖锐角不易伤人、周长一定时面积最大所以覆盖面积最大等等。但是却忘记了它是用来覆盖井口的,所以必须和井联系起来才行。为什么会经常听说有人不小心掉井里了,但是没听说过井盖掉入井中呢?因为它的直径大于井口的直径,所以掉不下去
- 领导态度
那为什么房子是方形的呢?
领导是否认可你,是一个很关键的因素。木头曾经在一个部门中四年没有得到晋升,原因是木头的老板说:木头很不错。可是木头的老板的老板说:木头还需要努力。于是木头最终选择离开那个部门,到了另外一个部门后,就得到了很公平的待遇,晋升得很顺利,五年晋升了三级
有人会抬杠了:鸟巢就是圆形的,很多迪拜的建筑也都是圆形的。但是这些都是非典型建筑,而是标志性建筑。典型建筑都是方形的,即使外部是曲面的,内部空间也一定会分割成方形的。一是因为设计和建造成本才会最低,二是可以更有效地利用内部空间,三是符合三维空间法则,人们不容易迷失方向
- 工作内容
#### 分析动态行为习惯
在一个团队中,有些人工作在项目 A而另外一些人为项目 B 工作。A 项目是一个新生的领域,发展很快,影响力大。但是 B 项目是一个维护已有系统的工作,不出错就可以了。显然 A 项目中的成员会有更多的晋升机会,大老板们也会偏向给 A 项目更多的 budget。
比如微软小冰在脱离微软以前,成员们像坐着火箭一样地晋升,当然 ta 们经常加班也是不争的事实。但是在脱离微软单独成立一个公司时,每个成员都被告知会降薪(因为成员们的级别普遍太高了)。
这里有两个关于做饭的有趣的故事。
- 积累效应
木头最近四年又一直没有得到晋升,但是心里却很平稳,因为这和上次的那个四年不一样,这一次的原因是在四年里换了四个老板:
- 第一次是因为项目被总部拿走编到别的团队了,不得不换到新团队;
- 第二次是因为整个团队都被砍掉了,不得不换到新部门;
- 第三次是因为老板跑路了,不得不换组;
- 第四次是因为上面所说的“团队规模”问题,又选择离开了,只有这一次是主动离开的,及时止损。
虽然在每个老板下的工作都很出色,但是每次都只有一年多的贡献积累,无法的得到晋升。在一个团队里,如果想得到高级别的晋升,无论如何也要两年左右,否则其它人会说闲话了:你看这个家伙刚来一年就晋升了,咱们干了三年多也没升职,不公平呀!
- 周边关系
不只是老板觉得你不错,其它同事也都觉得你不错,这样老板晋升你的决定才会服众。
还有就是你的工作成绩要有 Visibility可见性被大家知道否则你的老板一说起要晋升你时其它同级别或上级老板会有疑问ta 都做过什么项目,我怎么一直不知道这个人呀?这就比较尴尬了。
- 公司业绩
公司的盈利情况,以及所在领域的大环境是否好,都决定了公司是否有更多的 budget 来支持员工的升职。如果利润微薄,那么晋升的概率就小;本满钵满,晋升的概率就大。
OK如果你能够从以上几个方面分析好自己当前的境遇判断出哪一个因素才是“四年没有得到晋升”的关键抓住重点就能够“解决”这个问题提高自己的晋升概率。
### 3.2.4 提高解决问题的能力
善于观察,勤于思考。
造成一个问题的因素可能会有很多,找出这些因素,并通过对比测试、实例分析等手段评估自己当前所遇到的问题的根本原因是什么。
比如有人问你:为什么井盖一般都是圆的?你可能会嗤之以鼻地反问到:那为什么房子都造成方形的呢?因为你可能会下意识地认为那就是一种习惯或者约定俗成而已,为什么非得要刨根问底儿呢?
其实每一种自然现象都有背后的科学道理,每一种人文现象都有背后的社会学原理。井盖是圆形的,才不容易掉入井中;房子是方形的,设计和建造成本才会最低。
还有两个有趣的关于做饭的故事。
第一个是关于烙饼的故事:有一位中年妇女,很擅长烙饼,她每次把生面饼擀成圆形好,都要把生面饼的外缘切掉一厘米左右的宽度,在把缩小了直径的生面饼放入锅中。别人就问她:为什么要切掉一圈?她回答说:我母亲就是这么教我的。别人就去问她母亲,她母亲答道:因为以前家里的案板大但是锅小,所以要把生面饼切掉一圈再下锅烙。
第一个是关于烙饼的故事:有一位中年妇女,很擅长烙饼,她每次把生面饼擀成圆形后,都要把生面饼的外缘切掉一厘米左右的宽度,在把缩小了直径的生面饼放入锅中。别人就问她:为什么要切掉一圈?她回答说:我母亲就是这么教我的。别人就去问她母亲,她母亲答道:因为以前家里的案板大但是锅小,所以要把生面饼切掉一圈再下锅烙。
第二个关于煮饺子的故事:木头从小就爱吃饺子,妈妈总会在周末的时候包饺子吃。木头不会包饺子,就事先在锅里放上水,放在煤气炉子上烧开水。在煮饺子的时候,木头在旁边等着饺子出锅。在煮到一半的时候,沸水会成泡沫状溢出锅外,妈妈总会用一个大勺子盛满凉水兑入锅中,水就不会溢出了。这样反复三次,饺子就熟了,俗称“蜻蜓点水”。问妈妈为什么要点水?妈妈说以前姥姥就是这么教的。
木头觉得很奇怪,因为煤气开关明明可以关小,就可以不让水溢出。到了一定的年龄后,木头才想通:以前都是用煤球烧火,没有开关,煤球炉子产生的热量是无法控制的,所以只能用点水的办法控制锅内水温。之所以要点三次水,是因为祖辈的历史经验积累,点三次水后的时间大概就是 5 分钟左右,饺子刚好可以熟透。
木头觉得很奇怪,因为煤气开关明明可以关小,就可以不让水溢出。偶然看到电影里的情节,木头才想通:以前都是用煤球烧火,没有开关,煤球炉子产生的热量是无法控制的,所以只能用点水的办法控制锅内水温。之所以要点三次水,是因为祖辈的历史经验积累,点三次水后的时间大概就是 5 分钟左右,饺子刚好可以熟透。
点水据说还有其它的好处:
@ -276,3 +255,6 @@ OK如果你能够从以上几个方面分析好自己当前的境遇判断
但其实上面这些好处都是可以通过用“关小火 + 盖锅盖”的方式来实现的。
有句话叫做“知其然知其所以然”,就是要告诉大家遇事要多思考,找出表面现象后面的根本原因,才能融会贯通,遇到问题才会有解决的方法。

Просмотреть файл

@ -2,21 +2,21 @@
### 3.3.1 思维与系统化思维
#### 三个名词
#### 1. 三个名词
先理清三个名词思考Think思维Thinking思想Thought
<img src="img/Slide9.JPG"/>
<img src="img/Slide13.SVG"/>
图 3.3.1 三个名词的关系
思考,是一个动词,是人的大脑的一种能力和行为,就是程序员们常说的“等会儿!让我想想!脑子有点儿乱,这是我写的代码吗?看上去很乱......嗯,这个聚类算法并不适合于做有标签的数据分类学习,对吧?”
**思考**,是一个动词,是人的大脑的一种能力和行为,就是程序员们常说的“等会儿!让我想想!脑子有点儿乱,这是我以前写的代码吗?这么丑!看上去很难理解......嗯,这个聚类算法并不适合于做有标签的数据分类学习,对吧?”
思维,是一个名词,是思考的方法和角度,也可以说是一种习惯。思维的生理基础是大脑,但是相同的生理基础可以产生不同的思维方式,这是人脑最神奇的地方。思维有很多种分类,下面具体解释。
**思维**,是一个名词,是思考的方法和角度,也可以说是一种习惯。思维的生理基础是大脑,但是相同的生理基础可以产生不同的思维方式,这是人脑最神奇的地方。思维有很多种分类,下面具体解释。
思想,是一个名词,是思考的结果,它会形成两个层次的意识:认知、判断。“认知”是被动的,帮助人们认识世界;“判断”是主动的,帮助人们改造世界。成体系的认知叫做“知识”,伟大的认知一般才会称为“思想”,比如“毛主席是军事家、思想家、革命家”;渺小的判断叫做“主意”,大一些的叫做“决策”,商业化后叫做“解决方案”。
**思想**,是一个名词,是思考的结果,它会形成两个层次的意识:认知、判断。“认知”是被动的,帮助人们认识世界;“判断”是主动的,帮助人们改造世界。成体系的认知叫做“知识”,伟大的认知一般才会称为“思想”,比如“毛主席是军事家、思想家、革命家”;渺小的判断叫做“主意”,大一些的叫做“决策”,商业化后叫做“解决方案”。
#### 思维方式
#### 2. 思维方式
以下是一些互相对立的思维方式或习惯。
@ -28,7 +28,7 @@
- 线性思维与发散思维
- 程序员大部是线性思维的,逢山开路,遇水搭桥,因为要解决问题,所以总会找最简单最直接的解决方法。
- 程序员大部是线性思维的,逢山开路,遇水搭桥,因为要解决问题,所以总会找最简单最直接的解决方法。
- 发散思维是人脑天生的思维方式,测试人员大部分是这种思维方式,因为要制造问题,想办法用各种测试用例让代码暴露问题。
@ -63,21 +63,77 @@
- 双赢思维Win-Win是双方合作的基础在保持各自底线的前提下把竞争变成合作获得各自的利益。微软放弃自己的 IE 浏览器,转而采用 Chromium 内核做 Edge 浏览器是一种单方面的双赢思维Google 对此当然是欢迎的,而微软得到的好处是站在巨人的肩膀上让自己看得更远。
#### 从解决简单问题到系统化思维
#### 3. 从解决简单问题到系统化思维
先回忆一下 2.5 节中提到的“解决问题的能力”的主要内容。
先回忆一下 3.2 节中提到的“解决问题的能力”的主要内容。
通常来说,一个问题会包含有多个因素,这些因素都是**并列关系**,在拓扑结构上,如图 3.3.2 的**星形结构**。在某个特定条件下,只有一个因素会引发这个问题的出现。发现这个引发因素并加以解决,就是“解决问题的能力”体现。
通常来说,一个问题会包含有多个因素,这些因素都是**并列关系**,在拓扑结构上,如图 3.3.3 的**星形结构**。在某个特定条件下,只有一个因素会引发这个问题的出现。发现这个引发因素并加以解决,就是“解决问题的能力”体现。
而本节中的“系统化思维能力”所面对的问题,不仅仅是简单的一对一的因果关系,更多的是如图 3.3.2 中另外四种形式所示的复杂关系。所以,解决(简单)问题的能力也可以看作是一种简单的系统化思维能力。
<img src="img/Slide10.JPG"/>
<img src="img/Slide14.SVG"/>
图 3.3.2 系统化思维的几种形式
**这些思维形式的形成,是因为系统(问题)本身就是这种结构**,而并非无中生有。“读万卷书行万里路”是形成系统化思维的必经之路,简单说就是见多识广。
**这些思维形式的形成,是因为系统(问题)本身就是这种结构**,而并非无中生有。“读万卷书行万里路”是形成系统化思维的必经之路,简单说就是见多识广。读书是为了增加理论知识,行路是为了增加实践知识。
### 3.3.2 串行化系统与思维形式
**最终,形成系统化思维能力的目的还是解决问题。**
### 3.3.2 星形系统与思维形式
举一个比较通俗的例子:木头在某个级别上很长时间不能得到晋升,如何解决这个问题呢?
<img src="img/Slide15.SVG"/>
图 3.3.3 星形系统与思维形式
和解决技术问题一样,我们需要排查疑点,也就是影响晋升的因素都有哪些,如图 3.3.3 所示,它是一个星形的因果关系图。
- 个人能力
个人能力是根本,这也是本章要阐述的重点。木头在这一方面还是很有自信的。
- 团队规模
在一个只有五个人的团队里,晋升的难度取决于你的老板是否受你的老板的老板重视(即你的老板的影响力),如果是的话,你很容易晋升,否则就很难,那么尽早离开是最好的选择。木头曾经在这个问题上用了一年多的时间才领悟到。
如果一个团队同一级别的人多,那么大家的竞争就会比较激烈,当然这种竞争不会直接表现出来,而是在老板那里做平衡,最常见的情况就是“风水轮流转,今年到我家”。
- 领导态度
领导是否认可你,是一个很关键的因素。木头曾经在一个部门中四年没有得到晋升,原因是木头的老板说:木头很不错。可是木头的老板的老板说:木头还需要努力。于是木头最终选择离开那个部门,到了另外一个部门后,就得到了很公平的待遇,晋升得很顺利,五年晋升了三级。
- 工作内容
在一个团队中,有些人工作在项目 A而另外一些人为项目 B 工作。A 项目是一个新生的领域,发展很快,影响力大。但是 B 项目是一个维护已有系统的工作,不出错就可以了。显然 A 项目中的成员会有更多的晋升机会,大老板们也会偏向给 A 项目更多的 budget。
比如微软小冰在脱离微软以前,成员们像坐着火箭一样地晋升,当然 ta 们经常加班也是不争的事实。但是在脱离微软单独成立一个公司时,每个成员都被告知会降薪(因为成员们的级别普遍太高了)。
- 积累效应
木头最近四年又一直没有得到晋升,但是心里却很平稳,因为这和上次的那个四年不一样,这一次的原因是在四年里换了四个老板:
- 第一次是因为项目被总部拿走编到别的团队了,不得不换到新团队;
- 第二次是因为整个团队都被砍掉了,不得不换到新部门;
- 第三次是因为老板跑路了,不得不换组;
- 第四次是因为上面所说的“团队规模”问题,又选择离开了,只有这一次是主动离开的,及时止损。
虽然在每个老板下的工作都很出色,但是每次都只有一年多的贡献积累,无法的得到晋升。在一个团队里,如果想得到高级别的晋升,无论如何也要两年左右,否则其它人会说闲话了:你看这个家伙刚来一年就晋升了,咱们干了三年多也没升职,不公平呀!
- 周边关系
不只是老板觉得你不错,其它同事也都觉得你不错,这样老板晋升你的决定才会服众。
还有就是你的工作成绩要有 Visibility可见性被大家知道否则你的老板一说起要晋升你时其它同级别或上级老板会有疑问ta 都做过什么项目,我怎么一直不知道这个人呀?这就比较尴尬了。
- 公司业绩
公司的盈利情况,以及所在领域的大环境是否好,都决定了公司是否有更多的 budget 来支持员工的升职。如果利润微薄,那么晋升的概率就小;本满钵满,晋升的概率就大。
OK如果你能够从以上几个方面分析好自己当前的境遇判断出哪一个因素才是“四年没有得到晋升”的关键抓住重点就能够“解决”这个问题提高自己的晋升概率。
### 3.3.3 串行化系统与思维形式
如果读者参观过现代化的汽车制造流水线,或者是任意一家现代化工厂,都会看到串行化系统的具体实例。我们常说的软件系统的数据处理 Pipeline实际上就是借用这些串行化系统的概念。下面说说串行化思维形式。
解决单个问题,只需要线性思维就可以了,就是所谓“头疼医头脚疼医脚”。如果问题的依赖链条较长,就需要串行化的“系统思维能力”了,这是系统化思维中最简单的形式。
@ -85,12 +141,11 @@
要解决这个问题需要一系列的假设数据支持,有些数据是可以从网上查到的,有些是常识,剩下的就需要靠推理了。
<img src="img/Slide11.JPG"/>
<img src="img/Slide16.SVG"/>
图 3.3.3 北京有多少个加油站
图 3.3.4 北京有多少个加油站
正确的解题思路如下:
正确的解题思路如图 3.3.4 所示,详细解释如下:
#### 1. 北京有多少人口?
@ -157,31 +212,67 @@
所以最后的答案就是 1400 个加油站。如果推算出 1000~1500 个,都是在合理范围内。
#### 小结
#### 9. 小结
以上 8 个问题,每个问题都不是很难,难的是可以把它们串起来,最后解决一个系统性的问题,那么市政府对加油站建设的规划就可以按照这个推断来进行。数量少的话,车主加油会等较长的时间;数量多的话,加油站的利用率较低,经济上不划算。
这种思维形式的难点是:
这种思维形式的常见误区是:
- 不容易找到合理的上游依赖问题,很容易发散。
- 不能正确地解决每个依赖的问题,差之毫厘谬之千里。
- 堆栈较深(依赖链条长)时,没有信心/耐心继续下去。
既然有串行化的思维形式,那么有没有并行化的思维形式呢?有!但是其具体表现形式是下面要介绍的金字塔状思维形式和网状思维形式。
### 3.3.4 金字塔形系统与思维形式
### 3.3.3 金字塔状系统与思维形式
在计算机硬件系统中,设计了各种各样的存储设备,这些设备成明显的层次结构,但是上小下大,介于串行系统与下面要讲的金字塔形系统之间,如图 3.3.5 所示。
<img src="img/Slide12.JPG"/>
<img src="img/Slide17.SVG"/>
图 3.3.4 如何举办一场音乐会
图 3.3.5 金字塔形系统与思维方式
#### 0. 总体目标
先简单解释一下图 3.3.5 中的名词,见表 3.4.1。
表 3.4.1 存储设备列表
|英文名词|中文名称|数量级|
|--|--|--|
|Regs|寄存器|几十个到几百个|
|L1 Cache|一级缓存|32K|
|L2 Cache|二级缓存|256K|
|L3 Cache|三级缓存|8M|
|DRAM|计算机内存|几个G|
|Local SSD|本地固态硬盘存储|几百G|
|Remote HDD|远程磁盘存储|几个T|
每个上级存储(小而快)都是下级存储(大而慢)的高速缓存,目的是把常用的数据保存在高速缓存中,加快数据的存取速度。对于思维而言,下层存储海量的碎片信息,上层存储经过加工、抽象后的信息。
1988 年知名组织理论家罗素·艾可夫Russell Ackoff在就任国际一般系统研究学会International Society for General Systems Research主席的发言中提出了数据—信息—知识—智慧DIKWData-Information-Knowledge-Wisdom的知识三角形知识金字塔
这个 DIKW 和图 3.3.5 所示的系统,在原理上是相通的:把下层的东西提取出精华来放在上层。比如表 3.4.2 所示的几种进化过程:
表 3.4.2 从数据到智慧的进化
|Data$\rightarrow$|Information$\rightarrow$|Knowledge$\rightarrow$|Wisdom|
|-|-|-|-|
|一年中某地<br>下雨的数据|发现夏天午后经常下雨|于是夏天出门带雨伞|做出准确的天气预报|
|全国及地方的<br>人口数量数据|经过加工分析得到的统计<br>数据,比如地域性的差异、性别的差异、增长率的变化|建立人口模型,预测<br>未来人口数量的发展|辅助地方政府决策|
|姓别/年龄/职业/消费等零散数据|关联这些数据,得到它们<br>与消费金额的关系|年轻白领女性花钱最多<br>年长蓝领女性消费最少|不同消费群体的引导|
### 3.3.5 树形系统与思维形式
树形多用于组织结构,虽然外轮廓也和金字塔形系统一样是三角形,不同的是,处于低层的元素不是同质的。
<img src="img/Slide18.SVG"/>
图 3.3.6 如何举办一场音乐会
#### 1. 总体目标
木头有一个大乐队50 多人,都是微软员工,来自各个部门,木头是这支乐队的队长。平时排练,但是没有什么合适的演出机会,于是,木头想自己举办一个音乐会。
怎么开始筹备呢?
#### 1. 要素分解
#### 2. 要素分解
俗话说:没吃过猪肉还没见过猪跑吗?木头虽然没有举办音乐会的经验,但是看了那么多音乐会,也大概其知道组成一场音乐会的要素有三:
@ -189,7 +280,7 @@
- 观众部分
- 场地部分
#### 2. 解决方案
#### 3. 解决方案
- 表演部分
@ -208,18 +299,18 @@
但是平时排练也要有场地,好在公司相关领导很支持木头的计划,排练场地就放在大会议室里,一般都是晚上排练,不会影响白天开会。
#### 3. 执行计划
#### 4. 执行计划
- 先把演员们分成多个小组,或者自由组合,每个小组负责一个曲目。
- 先把歌手乐手们分成多个小组,或者自由组合,每个小组负责一个曲目。
- 曲目选择好以后,要进行编曲,然后大家开始排练。
- 排练用的乐器有“吉他、贝斯、键盘、鼓”四大件儿,其它的一些特殊乐器,比如小提琴、口琴、笛子等等由乐手自己准备。
- 由于排练场地只有一个,不同的组排练都有不同的时间,事先安排好
- 由于排练场地只有一个,要事先安排好每个组的排练时间不能冲突
- 海报部分,乐队内恰巧有 designer设计师当仁不让地负责设计海报。
- 海报设计完成后,一是形成 16:9 的电子版在楼内的各个演示屏上滚动播出,二是可以拿出去印刷,便于张贴。当然还需要中英文两个版本。
- 舞台搭建在演出日期前一天完成,各个小组按演出顺序进行彩排。
- 音响在一场音乐会里至关重要,木头特地找领导购买了调音台、线材、功放、音箱等设备。
#### 小结
#### 5. 小结
- 一个复杂的问题(目标)由多个要素组成,也就是子目标。
- 而完成这些子目标需要完成一个或几个任务。
@ -227,19 +318,19 @@
- 从时间上看,以海报任务为例,设计、印刷、张贴、回收,是前后阶段顺序,每个阶段都需要有人、有场地、有方法、有工具才能完成。排练场地本身是一个空间,但是也需要时间的计划才能安排好很多组的排练。
- 从空间上看,以场地为例,舞台搭建的位置、音响布置的覆盖面、调音台中控的地点、有长度限制的线材的连接方式、观众的座椅位置、录音录像师的机位、乐器在舞台上的摆放位置、麦克风的排列形式,等等等等,都是需要联动考虑的问题。
### 3.3.4 环状系统与思维形式
### 3.3.6 环形系统与思维形式
<img src="img/Slide13.JPG"/>
<img src="img/Slide19.SVG"/>
图 3.3.5 环状系统的负反馈
图 3.3.7 环状系统的负反馈
先看一种比较简单常见的环状反馈系统。其原始系统如图 3.3.5 左上所示,只有“输入、信号处理、输出”三个环节。
先看一种比较简单常见的环状反馈系统。其原始系统如图 3.3.7 左上所示,只有“输入、信号处理、输出”三个环节。
但是经常有这种需求:当输出端电平太高时,需要输入端智能地调低电平,所以就在输出端增加一个采样点,把输出信号反馈给输入端,并在结合点上与输入信号电平相减(因为是负反馈),这样在输出端最终得到的就是一个相对平稳的信号。
在思考时,通常人们会认为自己的思想无比正确,主意无比美妙。但是当你说出你的主意并得到一些 feedback反馈会纠正你的一些错误想法把这些信息加入到输入端重新思考才会得到大家都认可的好主意。
还有一种比较复杂的形式,一个输入通常是经过了很多个环节处理,最后反馈回来,对最初的输入做矫正。如图 3.3.5 的右图所示的一个例子:
还有一种比较复杂的形式,一个输入通常是经过了很多个环节处理,最后反馈回来,对最初的输入做矫正。如图 3.3.7 的右图所示的一个例子:
1. 用户:“现在的系统运行有些慢,希望能够提升一下整体效率。”
@ -252,23 +343,23 @@
本来是一个好的出发点,但是经过一个环状的系统走下来,反而事与愿违。用户在得到一个好处(运行性能提高)的同时,可能会等待更长的时间获得新功能,或者花更多的钱来购买设备。
### 3.3.5 网状系统与思维形式
### 3.3.7 网状系统与思维形式
网状系统(或者说是表格形式)思维是最复杂的一种形式,因为它涉及到了横向思维和纵向思维两个方向,甚至是多维的。而其它的思维形式都是单向的。
<img src="img/Slide14.JPG"/>
<img src="img/Slide20.SVG"/>
图 3.3.6 环状系统的负反馈
图 3.3.8 网状系统的负反馈
在软件开发过程中,如图 3.3.6 所示,从纵向看,通常是多个小组分别完成各自的子系统,每个子系统又包含一系列的模块。从横向看,不同子系统的模块组成一个端到端的功能。项目管理者在纵向上需要协调各个小组的进度,这样才能在横向上把不同子系统的功能串联起来,尽早得到一个可运行的系统。
在软件开发过程中,如图 3.3.8 所示,从纵向看,通常是多个小组分别完成各自的子系统,每个子系统又包含一系列的模块。从横向看,不同子系统的模块组成一个端到端的功能。项目管理者在纵向上需要协调各个小组的进度,这样才能在横向上把不同子系统的功能串联起来,尽早得到一个可运行的系统。
在机器学习中,通常有很多参数需要调节,比如深度神经网络中的步长值、样本批大小、卷积核的尺寸、正则化的参数等等,这些参数互相影响,网格状的参数搜索可以帮助我们找到最佳的参数组合。
<img src="img/Slide15.JPG"/>
在软件质量控制过程中,如图 3.3.9 所示,需要软件可以达到很多种质量指标,如:正确性、可靠性、易用性、高效率、可维护性、可移植性等等。但是其中的某些指标是相克的,一个指标的提升会带来另外一个指标的下降。
图 3.3.7 质量指标之间的竞争
<img src="img/Slide21.SVG"/>
在软件质量控制过程中,如图 3.3.7 所示,需要软件可以达到很多种质量指标,如:正确性、可靠性、易用性、高效率、可维护性、可移植性等等。但是其中的某些指标是相克的,一个指标的提升会带来另外一个指标的下降。
图 3.3.9 质量指标之间的竞争
在足球场上,教练会强调两点:一是全队三条线在横向上的步调一致,一起压上进攻,或者一起收缩防守;二是在纵向上,同一边的后卫、中场球员、前锋要协调进攻。在排球场上,六个队员形成 2x3 的网格阵型,兼顾进攻与防守。

Просмотреть файл

@ -1,5 +0,0 @@
<img src="img/Slide21.JPG"/>
<img src="img/Slide22.JPG"/>
<img src="img/Slide23.JPG"/>

Просмотреть файл

@ -0,0 +1,212 @@
## 3.5 认知能力的培养
认知能力的关键说起来很简单,就是**理论$\leftrightarrow$实践**的循环体。培养认知能力的基本步骤:
1. 互通有无,用沟通能力打开封闭的世界。
2. 保持好奇,不断学习,保持和提高学习能力。
3. 学以致用,用学到的知识去解决实际问题,提高对细节的理解能力。
4. 洞达事理,培养系统化思维能力,建立知识体系,激发创造能力。
其实就是本章中的前四个小节所讲的内容。接下来笔者用一些亲身体会到的最佳实践来分享一些学习方法和技巧,以此来提高认知能力。
### 3.5.1 学习方法
#### 1. 费曼学习法
这个学习方法是诺奖获得者费曼提出来,然后由后人总结发展出来的。其核心就是先阅读大量资料,然后找出其中的知识,再把这个知识用自己的方式讲给一个完全不懂的人。如图 3.5.1 所示,可以表示为通过输入、输出来控制学习行为,验证学习效果。
【最佳实践:知识共享】
在微软的团队中,老板一般会组织大家进行技术交流,无论是与工作相关的还是无关的都可以。每个人根据自己的兴趣爱好在业余时间学习新的技术知识,然后把它们组织成 PPT 形式,在每周的开发人员组会时(不是 Scrum Meeting讲给大家听时间在半小时左右每周一人。大家可以任意时间打断演讲提出问题。
【最佳实践:小黄鸭调试法】
另外一个极端的例子是小黄鸭调试法:程序员总是在桌子上放一只橡皮小黄鸭,在调试代码的时候详细地向鸭子解释每行代码。如果没有小黄鸭玩具,找一个同事临时充当也行,千万不要用尖叫鸡代替。你会发现在讲解的过程中,可以突然发现一些隐藏的问题,从而帮助你快速解决 Bug。其原理是你如果只是盯着代码看大脑会忽略一些重要细节而当你试图讲出来时为了让对方听明白就会揪出这些细节来。从而发现问题。
<img src="img/Slide22.SVG"/>
图 3.5.1 两种推荐的学习方法
【最佳实践:如何做好小黄鸭】
如果某个读者不幸被同事当作小黄鸭,一定要拿出程序员的基本素养来,面带微笑认真地听,时不时地点头,也可以提出一些疑问,但是不要打断同事的思路。当同事忽然发现隐藏的 Bug 时,通常会立刻陷入深度思考而置你于不顾,此时默默地离开即可。
#### 2. SQ3R 阅读法
SQ3R 代表着五个单词:
1. **S**urvey浏览浏览学习内容。比如拿到《智能之门》笔者的另外一本书先看章节目录第四章是单变量线性回归。
2. **Q**uestion提问对一些知识点提出初步的问题。比如训练数据长得是什么样子回归的数学模型是什么公式最小二乘的数学原理是什么梯度下降的公式是如何得到的又是如何变成代码执行的
3. **R**ead阅读带着问题深入阅读并找到答案。
4. **R**ecite背诵把书合上或者只看标题来默写最关键的梯度下降公式推导并写代码实现。
5. **R**eview复习过几天后重复 4看看是不是能记住。
如图 3.5.1 所示,可以理解为带着问题学习,最后得到答案。
#### 3. 西蒙学习法
笔者认为,对于理工科读者而言,这不是一个靠谱的学习法,但是不妨拿出来供大家参考。
这是诺贝尔经济学奖获得者西蒙教授提出来的。其理论基础是:
1. 一门学问大概有 5 万个信息块(知识点);
2. 一个人记忆remember一个信息块需要 90 秒;
3. 5 万个信息块需要 1250 个小时;
4. 一周学习时间为 35 个小时,复习 5 个小时;
5. 1250 小时 / 35 小时 = 36 周 = 9 个月。
在原理论中的一些不妥之处:
- 5 万个信息块需要 1000 小时,这与 50000 x 90 秒 / 3600 秒 = 1250 小时相差太多,需要精确一些。
- 每周学习时间为 40 小时,但笔者认为不复习 5 个小时的话,会出现“狗熊掰棒子”的情况。
- 知识点有难有易,不能平均。
- 知识点之间有联系,需要读者自己组成知识体系。
西蒙教授的结论是:一个有一定基础的人,只要肯花时间下功夫,在最多 9 个月内可以掌握任何一门学问。
这听上去很疯狂,并且也没有定义“掌握”是如何定义的,但是笔者认为大学本科甚至研究生的课本,在 3 个月内就可以读完remember然后再花几个月理解understand并应用apply
### 3.5.2 学习画图
人们在描述一个复杂问题时,通常会用画图的方式来表达,一图胜千言。为什么呢?因为人脑理解语言的过程如图 3.5.2 所示。
<img src="img/Slide23.SVG"/>
图 3.5.2 从语言序列重建模型
讲述一个复杂的问题时,如果用语言方式表达,则是一个序列结构,如图左侧所示。对于听者来说,如果只有一两句话,那理解起来很容易,但是当这个序列很长时,人们不得不在头脑中建立起右侧子图的结构来帮助理解,还有可能产生误解。所以,如果说话的人一开始就在纸上画出图来然后解释,会到达事半功倍的效果。
我们举个例子:当有一个人对你说“有一个系统,它的输入是文字,输出是图片”时,你的脑海中一定会快速建立起类似图 3.5.1 所示的模型(输入文字$\rightarrow$系统$\rightarrow$输出图片),然后大脑可能会把它立刻擦除,但是当再次需要的时候,又可以立刻把它从“垃圾桶”中捡回来而无需重建。
画图是抽象思维$\leftrightarrow$具象思维来回转换的结果,善于画图,说明你对这种转换掌握得淋漓尽致。我们在平时写技术文档的时候,通常会配上几张图来说明系统框架、基本流程、状态转换、交互关系等设计理念,让文档审阅者一目了然。
画图和写字一样,也有好看与不好看的区别,笔者提供一些体会供大家参考。
【最佳实践】
- 大小统一:同一级别的所有方框都尽量保持大小统一,里面的字体字号也要一致。
- 横平竖直:方框之间要对齐,像打麻将时自己的手牌一样,不能像打扑克牌一样。
- 配色讲究:要有基本的美学概念,不能使用大红大绿,而是要用一个色系的颜色做配色。
- 生动形象:绘图工具一般都很丰富,可以选择用图标表达各种含义。
- 连线清晰:尽量避免有交叉线的出现,重叠的连线要保持拓扑清晰。
- 妙用线型:巧妙使用“粗细虚实弯直”等线型来表达不同的含义。
图画得漂亮的人,一般长得也漂亮。
在本书中,所有的插图都是笔者亲手在 Microsoft PowerPoint 上绘制的SmartArt 功能帮了大忙,帮助笔者对各种概念的理解更为深刻,相信对读者在阅读本书时也有同样的效果。
还有一种叫做“思维导图”的东西,是英国人托尼·博赞发明的,他是世界记忆锦标赛和世界快速阅读锦标赛创始人,曾经帮助英国查尔斯王子提高记忆力,被称为记忆力之父。于是,很多人把思维导图推崇至上,甚至升级为一种学习方法。对此笔者有不同看法。
其实,思维导图的方法和罗列多级列表的方法,在内容上没有任何区别,只不过思维导图工具具有特别的**形状、颜色、位置、关系连线**等信息,可以根据这些不同于纯文字的额外信息来辅助记忆。另外,思维导图最好是**读者自己绘制**,这样对绘制的过程(也就是思考和归纳的过程)有很深刻的记忆。
所以,绘制思维导图收益最多的是绘制者自己,而不是其它读者。
### 3.5.3 学习写字
笔者回忆了一下上学的经历以及自学新知识的过程,大概经过了如图 3.5.3 所示的几个阶段,下面详细介绍这几个阶段的【最佳实践】。
<img src="img/Slide24.SVG"/>
图 3.5.3 构建知识体系
#### 1. 写笔记
**主要作用:机械记录,随时记录知识要点。给自己看。**
**留存率10%。** 意味着基本会忘得一干二净。
“好脑子不如烂笔头!” 小学老师总是在课堂上向坐在那里发呆的同学吼出这句话。确实,写笔记是一个帮助记忆的过程,回忆那些在小学、中学时学习成绩好的同学,他们的笔记都是非常工整完备的,主要是记录老师的板书,以及老师口头讲的但书中没有的知识点。
但是到了大学,没有老师要求你记笔记,最方便的笔记其实是直接标出书中的重点或者写在书的空白处,就像《哈利波特与混血王子》中的那本魔法书一样。
#### 2. 写短文
**主要作用:拾遗补缺,自我弥补技术盲区。给朋友看。**
**留存率30%。** 很长时间以后还能记得自己写过这东西,但具体内容忘记了。
这里所说的“短文”,可以是一篇简短的记录,或者是一个简单的设计文档,甚至可以是 PPT 文档。
正如同费曼学习法所说的,我们如果把学习到的知识经过消化后用自己的语言再给同事们讲解出来,就会有深刻的理解。因为在准备讲解的过程中,你会发现有一些细节没有搞清楚,还有一些环节没有连接上,最糟糕的是结论和原因可能对不上,这都是没有透彻理解而导致的。如果想弥补这些问题,你必须深入地学习、透彻地理解。
在中学时代的语文课要求写 800 字的作文,对于所有学生来说都是一个噩梦,包括那些语文成绩好的学生,写作文对他们来说也不是轻而易举的事情,尤其是在考试的时候,时间有限,还要兼顾其它的小分题目。现在看来,一本 16 开版面的书的一页就是 800 字左右,可以算是一篇短文了。如果那时打好基础,以后遇到码字的工作时会轻松一些。
#### 3. 写案例
**主要作用:经验转播,深入实际动手实践。给学生看。**
**留存率50%。** 在需要的时候可以方便地通过查询得到,重温知识,并再次使用。
这种案例的内容比较宽松,可以是各种层次或方向的技术内容,比如:
- 如何安装配置 GPU 显卡驱动和 CUDA 开发包。
- 如何使用 VS Code 利用 Linux 做远程服务器来开发 Python 代码。
- 如何使用 UWP 中的 GroupList 控件来完成炫酷的用户交互界面。
- 如何使用 Azure 上的 Cognitive Service API 来完成 Text-to-Speech 调用。
- 如何使用 PyTorch 搭建并训练简单的神经网络模型。
- ......
这种文章不要求很强的文字功底,只需要一板一眼地把步骤写出来即可,但最好是图文并茂,避免使用过多的文字还说不清楚。另外,作者自己的试验环境可能和读者的机器不同,比如 Python 版本,所以要想正确全面,需要多做些试验。
#### 4. 写博客
**主要作用:知识普及,分享探讨技术问题。给从业者看。**
**留存率70%。** 可能会忘记一些细节,但方法不会忘记,而且会融会贯通地应用于实践。
一些技术博客(比如 CSDN 或 cnBlogs、知乎上的技术问答、小红书上的技术讲解、微信公众号上的技术文章等等都属于这个范畴。
《构建之法》的作者邹欣老师,就非常看重写技术博客的作用。当年在邹老师手下一起做 Windows 10 的生态环境建设时,整个开发小组都在一边开发一边写博客,每周定期对外发布一篇,内容是在 Windows 10 的 UWP 应用开发过程中遇到的问题及解决办法,很受广大粉丝的欢迎,最佳记录是一篇博客可以到达几万的阅读量和上百个点赞。
由于是对公众发布,比在团队内部做分享要严肃得多,内容要有代表性,篇幅要有保证,技术含量不能太低,用词也需要正式些,确实是很锻炼人的逻辑思维和表达能力的。
#### 5. 写教程
**主要作用:体系建设,讲解知识广泛传播。给广大读者看。**
**留存率90%。** 意味着基本不会忘记,而且可以用于指导他人。
这里的教程,主要指的是书籍、教材、课件等等,还有一些特殊的视频类教程。教程的主要特点是:
- 知识点准确
写作者对自己的文字产出高度负责,白纸黑字印出来的东西不能误人子弟,所以力求完整、正确,每一个概念都有出处可查,每一个试验都有代码有结果,每一行公式都反复核对,每一张图都认真推敲......
- 有完整体系
一本书不会只讲几个知识点,而是把这些知识点串起来形成一个体系,其体系结构有可能是 3.4 节中所讲的五种结构中的一种或几种混合。这种知识体系帮助读者在阅读完后,利用其中的一个或几个知识点来解决实际问题。
- 理论加实践
写作者一般都是在该领域有丰富的实践经验,把这些经验总结出来,结合已有的理论知识,变成循序渐进、深入浅出的文字、图片、公式、代码,以写作者认为读者最容易接受的方式来传播知识。
写书时不能人云亦云,比如很多人说 SVM支持向量机中的高斯核函数可以用泰勒展开来解释其工作原理但是经笔者试验后根本不是那么回事儿。
写一本书要看十本书,写作者必须有严谨的治学态度,克服长期的孤独寂寞,并具备舍己为人的品质才有可能成功,因为写书真的不挣钱(除非是畅销书)。
如果最开始时自己没有能力写出完整的一本书,那么与有经验的作者合作也是一个办法,前提是那位作者愿意带新人并分享著作权。一般情况下在 40 岁以后才有可能有写作的基础和动机,二、三十岁时可以暂时不考虑写书,但是可以用前面 4 个阶段的方法逐步积累素材。
#### 6. 写论文
**主要作用:创新引领,开拓新的知识领域。给研究者看。**
**留存率95%。** 不会忘记自己写过的论文,从思路到过程,从文字到数据,都会记忆犹新。
笔者是一名软件工程师,对研究领域并不熟悉。但是在研究院工作的一段时间内,接触了很多研究员,也了解了他们的一些工作过程。
笔者的一位研究员朋友小 H 对此有一番感慨:“写论文太难了,从开始学习时就难,只能跟着 mentor 一步步走,让你干什么你就干什么。自己亲身经历过一遍全过程后,就假装算学会了。但是当要自己独立选择方向、立题、搜集素材、设计试验、总结结论、构思结构、润色文字时,每一步都需要艰苦的努力,无论你是新手还是老手,都不能保证每一篇论文都可以入选。”
在笔者看来,论文和教材的主要区别是:
- 读者不同
论文读者一般都是领域研究人员(否则根本就读不懂)。而书的读者可以是任何有一定基础知识的人。
- 目标不同
论文讲究的是知识的创新,不需要赘述已有知识。而书讲究的是知识的传播,要有知识点的铺垫,不能只定位在前沿知识讲座,否则就成了论文集了。
- 篇幅不同
每篇论文只讲一两个创新点,篇幅上能短则段,把问题讲清楚即可。每本书要讲一个体系的知识,力求完整准确。
- 方法不同
论文一般要求在几个月内完成,抓住一个创新点深入挖掘。书一般是需要几年的时间才能完成,每个知识点都要深入挖掘。
所以,一般写论文的人写不了书,写书的人写不了论文。但是写论文的人可以在积累了一定数量的创新后,把它们组织成为一个全新的知识体系变成书。
小 H 还向笔者透露了一个做研究写论文的关键点:批判性思维。于是笔者做了一番信息调查和知识梳理:在 3.2 节中讲到的布鲁姆分类体系中的高阶认知范畴:“分析、评价、创造”,即,批判性思维是高阶认知范畴的一部分。批判性思维的英文 Critical Thinking 并非像中文的“批判”这么尖锐,而是在一股脑接受一些信息、理念、观点之前,有四个动作可以做:
- 先根据高阶认知能力进行分析、评价,如果合理则接受,作为写论文的基础;
- 如果发现有不合理的地方,则可以作为创新点深挖一下,作为写论文的立意;
- 如果都合理,但是感觉有不充分的地方,可以在现有基础上做进一步的创新扩展,也可以写出论文来。
- 如果都合理,但是解决不了某个特定问题,那么必须创造一套新的方法,这自然可以成为论文的基础。
#### 总结
其实布鲁姆分类体系的六个层次,与本节中所讲的建立知识体系的六个阶段也可以有比较模糊的一一对应关系的,请读者自己分析理解。所以,掌握了本节中的六个阶段的学习方法,自然也就达到了布鲁姆分类体系的六个层次。

Просмотреть файл

@ -0,0 +1,16 @@
## 3.6 练习
https://zhuanlan.zhihu.com/p/87140332
体会费曼学习法
在一个团队内,大家分工:
- 在学习一些新技术时,大家不妨用 OneNote 记录笔记,重温一下学生时代的习惯;
- 然后,把上面这些知识点,整理成几页 PPT给同事们讲解
- 遇到一些流程化的东西时,可以详细记录其操作步骤,图文并茂,然后写成案例发表在网站上;
- 自己解决了一个具体的技术问题后,把前因后果写成一篇技术博客,发表在网站上;
- 团队中的每个人都发表了技术博客后,一起讨论如何把它们组织成一个完整的知识链条,按章节排好顺序,组成博客集,相当于是一本书的雏形。
- 关于论文,就不需要动手实践了,因为没经过训练的人是不可能完成的,我们这些软件工程师也不靠这个吃饭,不练也罢。

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 52 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 46 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 86 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 56 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 115 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 81 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 80 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 109 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 93 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 67 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 78 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 88 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 78 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 80 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 56 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 151 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 123 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 454 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 118 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 119 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 131 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 79 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 81 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 43 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 72 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 119 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 81 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 83 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 83 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 122 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 86 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 36 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 115 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 58 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 95 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 200 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 65 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 68 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 52 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 65 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 50 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 468 KiB

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше