[关闭]
@zhongjianxin 2017-07-26T17:17:12.000000Z 字数 2692 阅读 1616

Tasking

Trainning


image.png-284.7kB
image.png-103.9kB
image.png-50.7kB
image.png-96.9kB

本文的起源是因为思考一个问题,什么样的人适合做程序员。 我曾经苦恼得思考着这个问题,直到我在 SICP 上看到了答案。说的白话一点就是,能像机器一样思考的人就适合做程序员。

那么计算机这台机器是怎么思考的呢?这里是我的答案:我们所有的计算机,都是这个模型,江湖人称“冯・诺伊曼体系”

所有的问题都从输入和输出的角度去思考,这就是计算机这台机器的思考方式。也就是说你能做到这样思考,你就会像机器一样思考了。很简单吧,但是新的问题又产生了,处理自然要处理输入产生输出了。输入,输出是些什么呢?
机器在加工什么?SICP 中又说了,非形式的讲,我们只在处理两种东西,数据和过程,他们还不是严格区分的。

看我们的模型,中间处理的部分其实就是过程,输入和输出其实就是数据。(在冯诺伊曼体系里,数据和过程被称之为数据和指令)那说到数据,我们有一门学科叫做数据结构,它很好的表达了什么是数据。我们还有面向对象,类型系统之类的知识,他们都会帮助我们很好的定义数据。

下面我们拿几个例子来学习一下。我们来写一个加法函数,接受两个参数作为加数和被加数,返回一个和,这个太简单了,几乎任何一个程序员都可以在几秒钟内写完。拆成机器的思维是什么样呢?
加法函数

  1. 输入:
  2. a
  3. b
  4. 输出:
  5. result

大概就长这样,输入是a和b,输出是一个结果,我们起名叫result。它到底表达了个啥样的代码呢?大概长这样:(本文所有的代码都会采用javascript描述)

  1. function add(a, b) {
  2. return a + b;
  3. }

咦?result哪去了?在你调用的地方可能会有一行代码 var result = add(1,2);

这个表达方式不仅仅可以用来描述函数定义,用来描述表达式也是可以的。比如:

  1. 1. var result = a + b;

所以不仅仅可以用来描述函数定义,还可以描述代码块。。加上类型就变成了这样:

  1. 加法函数
  2. 输入:
  3. a: Number
  4. b: Number
  5. 输出:
  6. result: Number

我们做一个稍微复杂的。比如下面这个:写一个函数,可以选出一个由数字组成的集合当中所有的偶数的最大值。这回一步做出来可能就有点难了,没关系,我们可以成两步:

  1. 1. 选出集合中的偶数
  2. 2. 选出偶数中的最大值

这两步呢,按照我们之前的格式写一下,大概是下面这个样子:

  1. #1 选出集合中的偶数
  2. 输入:
  3. inputArray
  4. 输出:
  5. evenArray
  6. #2 选出偶数中的最大值
  7. 输入:
  8. evenArray
  9. 输出:
  10. max:Number

集合怎么表达:[Number]就可以了。(我们的一个好习惯是一个集合里不要放两种类型的元素)

  1. #1 选出集合中的偶数
  2. 输入:
  3. inputArray: [Number]
  4. 输出:
  5. evenArray: [Number]
  6. #2 选出偶数中的最大值
  7. 输入:
  8. evenArray
  9. 输出:
  10. max: Number

咦,第二步的evenArray没有写类型。嗯,因为evenArray是第一步的输出,我就把它省了,相信大家也能看明白。

画图帮助思考:
image.png-99.5kB
image.png-101.4kB

以上思考过程还是展示了:
1. 分解问题
2. 找到子问题之间的关联(通过输入输出关联起来)
3. 找到问题的边界,明确假设与结果
上述三点看着简单,却是思维清楚与否的关键。我们管这个能力叫Analytical Thinking。

Tasking Practice:

1.自己试着做FizzBuzzWhizz的Tasking

2.写一个程序来计算一个文本文件 words.txt 中每个单词出现的频率。
为了保持简单,假设:

words.txt 只包含小写字母和空格
每个单词只包含小写字母
单词之间由一个或多个空格分开

举个例子,假设 words.txt 包含以下内容:

the day is sunny the the
the sunny is is

你的程序应当输出如下,按频率倒序排序:

the 4
is 3
sunny 2
day 1

Tasking 概念图

image.png-504.6kB

1.输入输出穷尽

我们还是不太清楚怎么穷尽对吧。说是穷尽输入输出,到底输入输出都有多少大类呢?这个也是可以穷尽的。

a.输入总共有下面几大类:

  1. 参数
  2. 读取全局变量 

  3. 调用全局函数后得到的返回值 

  4. 读取局部作用域变量(比如this) 

  5. 调用局部函数后得到的返回值 

  6. hard code的数据

a.输出总共有下面几大

  1. 返回值 

  2. 修改全局变量 

  3. 调用全局函数时传的参数 

  4. 修改局部作用域变量(比如this) 

  5. 调用局部函数时传的参数

2.画图法:

我们的画图方法受时序图启发而发明,具体的规则如下:
1. 本图基本元素由方块和带箭头的线组成
2. 一个方块只代表一个函数或一个代码块,通常是函数,方块中可以写字,可以表达函数是属于哪个类或哪个实例等信息。
3. 指向方块的线代表该函数的输入,背离方块的线代表函数的输出。
4. 数据流动的时间轴遵守先从左到右,再从上到下的顺序。
5. 每一对输入输出(输入在上,输出在下)加一个方块,表达了一次函数调用。

画图可以有多种方式 输入输出的类型可以直接画在图中的箭头上

举例: 
比如下列代码:

  1. function c(){
  2. }
  3. function b(){
  4. c();
  5. }
  6. function a(){
  7. b();
  8. }
  9. a();

画成图是这个样子的
http://static.zybuluo.com/jtong/kjc93vf7lotu1uhl5682lhf7/a-b-c.pngimage.png-46.8kB

  1. example tasking:
  2. #1 生成成绩单view model
  3. 输入:
  4. studentIds: [String]
  5. 输出:
  6. scoreSheet: {
  7. studentScores:[{
  8. name: String,
  9. chinese: String,
  10. english: String,
  11. math: String,
  12. programming: String,
  13. average: String,
  14. summary: String
  15. }]
  16. summary: {
  17. totalAverage: Number,
  18. totalMidden: Number
  19. }
  20. }
  21. #2 打印成绩单
  22. 输入:
  23. scoreSheet
  24. 输出:
  25. result: String

PDCA(刻意练习):
image.png-54.9kB

Summary:
一个思维训练,对于这个思维训练,最重要的事情有三点:
1. 语文问题(用词精确,前后一致)
2. 接口问题(完全穷尽)
3. 每个函数之间互相不知道对方的内在实现(各自独立)
能做好这三点,代码就能完胜行业里的大多数人:)

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注