# 19. 测试

内核恐慌 · 2015-06-15

<https://lib.pan.icu/f80a1bc3-4e23-4b99-8007-fd2df63f559d>

本期节目中，吴涛和Rio首先讨论了HHKB键盘的使用体验与版本差异，Rio分享了从键盘布局到适应过程的感受。随后，两人读了两封听众来信：一封关于编程学习与恋爱关系的反思，另一封涉及文字编码历史，包括ASCII、Unicode、ISO/2022等标准，并吐槽了Windows的宽字节API。接着，他们简评WWDC，重点谈了Apple Watch的实用性与Swift 2开源的意义。最后进入本期主题“软件测试”，从瀑布模型与敏捷开发的对比切入，深入探讨了TDD（测试驱动开发）的三原则、BDD（行为驱动开发）与Cucumber工具、单元测试框架XUnit家族及Python的doctest，并讨论函数式编程对测试的友好性。两人对TDD持批判态度，认为其压抑创造力，但承认其在大型项目中的必要性。

## Questions this episode answers

### TDD（测试驱动开发）是什么？它的三个原则是什么？

TDD 要求在写功能代码前先写测试，遵循三个原则：先写一个会失败的单元测试，再写刚好让测试失败的测试代码，最后只写刚好通过测试的功能代码。它源自极限编程，通过小步迭代保证质量，但被吴涛批评过于机械，压抑创造力。

[1:49:21](https://lib.pan.icu/f80a1bc3-4e23-4b99-8007-fd2df63f559d?t=6561000)

### 为什么吴涛在节目中形容TDD“非常印度”？

吴涛用“非常印度”讽刺 TDD 将开发变成流水线，程序员成为可替换的“人力资源”，按蓝图重复执行任务，失去创造性。他认为 TDD 虽能保证质量，却像工业革命的大规模生产，在第三世界外包产业中尤为典型，是一种必要的恶。

[2:11:24](https://lib.pan.icu/f80a1bc3-4e23-4b99-8007-fd2df63f559d?t=7884000)

### 什么是软件的“发烟测试”（smoke testing）？这个术语的来源是什么？

发烟测试指验证软件最基本功能是否运行的初步测试，如启动服务器后看到“It works”页面。术语可能源于古老行业（如矿工通过冒烟判断设备启动）。它只求关键环节正常，不检查细节，类似合上电闸看灯是否亮。

[1:19:21](https://lib.pan.icu/f80a1bc3-4e23-4b99-8007-fd2df63f559d?t=4761000)

## Key moments

- **[0:00] 开场**
  - [0:39] 吴涛自称受演说家启发，通过含着小石子洗澡时背诵节目介绍来提升口才
  - [1:02] Q: 程序员如何通过增加难度来提升编程水平？ 吴涛回答：不用显示器写程序，就像绑沙包跑步
- **[2:38] HHKB键盘**
  - [2:38] Rio 从 Lawrence 处获赠 HHKB Pro 2 键盘，开始适应其键位
  - [3:28] Q: HHKB 键盘共有几个版本？有什么区别？ 吴涛解释 Lite 版有方向键，Pro 版无，且存在日文和国际布局差异
  - [7:33] HHKB Lite 可能采用非 TorPrate 开关，因此便宜且手感不同
  - [9:39] 频繁使用 HHKB 的 Fn 组合键导致吴涛右手小指疼痛
  - [11:16] Rio 在 HHKB 和 Mac 键盘之间因 Fn 键位置不同和 Emacs 键绑定的使用而感到人格分裂
  - [16:24] 吴涛用 HHKB Pro 2 一年多，已内化其键位，不再觉得不习惯
- **[17:22] 读者来信**
  - [19:56] 听众 Virgil Minh 来信指出 ASCII 中大写 A 是 65，实为 64+1，小写 a 是 97=64+32+1，体现编码内在逻辑
  - [21:34] Q: 逆波兰表示法为什么反直觉？ 本质上它是针对四则运算的递归优化，与 LISP 相通
  - [22:32] 90 后听众描述其成长环境中缺乏恋爱常识教育，认为 Learn it the hard way 在感情中可能导致不可逆伤害
  - [24:31] Rio 认为处理亲密关系的能力是做人基本，与职业如程序员无关
  - [25:22] 吴涛与 Rio 探讨中国 90 后在当前环境下谈恋爱是否仍然受限，与高考竞争相关
  - [26:34] 吴涛对刚高考完的听众说：“打算报计算机系，您千万别啊”
- **[47:49] WWDC短评**
  - [48:24] 吴涛获女友赠送 42mm 不锈钢 Apple Watch，这是他第一次每天佩戴手表
  - [49:32] 吴涛因初中时佩戴镀镍电子表导致镍过敏，此后任何活泼金属接触皮肤都会起包
  - [51:24] 吴涛认为 Apple Watch 的实用性不高，最实用功能是邮件通知和语音识别准确率高
  - [52:48] watchOS 2 将支持原生 SDK，应用可直接在手表上运行，改善当前远程桌面模式导致的慢和费电问题
  - [54:12] 吴涛发现 Apple Watch 的语音识别可自动中英文混用，准确率极高，甚至能识别“奥迪”为 A-U-D-I
  - [57:42] 吴涛评价 Apple Watch 是“nice to have”产品，尚未出现 killer feature
- **[1:18:23] 软件测试**
  - [1:19:09] Swift 2 引入 exception 机制，吴涛此前在知乎上撰文论证无 exception 更好，现在只能默默修改答案
  - [1:20:15] Q: 什么是软件测试？ 吴涛区分广义测试如渗透测试，狭义测试是可重复验证软件行为的方法
  - [1:22:05] 发烟测试 (smoke testing) 借自其他领域，指验证最基本功能是否运行，如打开开关看灯亮
  - [1:23:42] 功能测试验证软件行为正确性，非功能测试如性能测试验证速度等指标
  - [1:25:48] Rio 承认自己不写测试，吴涛调侃“伟大的程序员都是不写测试的”
  - [1:26:28] Rio 质疑 TDD 必要性，认为应从设计上保证正确性，而非依赖测试，吴涛认为测试被低估
- **[2:22:13] 测试工具**
  - [2:22:18] 四色定理的暴力证明被称为数学领域的 TDD
  - [2:22:53] 吴涛提及围棋 AI 通过蒙特卡洛算法随机穷举走法，使业余棋手无人能敌
  - [2:26:13] 几乎所有编程语言都有基于 Kent Beck 的 SUnit 模式的单元测试框架，如 JUnit、NUnit 等
  - [2:29:02] Python 的 doctest 允许在文档字符串中嵌入测试用例，将示例直接作为可执行测试
  - [2:31:26] 函数式编程因无副作用、输入输出确定，使得单元测试更容易编写
- **[2:32:22] 结尾**

## Speakers

- **Rio** (host)
- **吴涛** (host)

## Topics

软件开发, 键盘, 字符编码

## Mentioned

Apple Watch (product), Cucumber (product), Go (product), HHKB (product), JUnit (product), SUnit (product), Swift (product), Xcode (product), doctest (product)

## Transcript

### 开场

**吴涛** [0:00]
欢迎收听 IPN Podcast， 网络旗下的 IT 技术主题娱乐节目 《 内核恐慌 》。 我们号称 " 哈利口啊 "，但是也没有干货 。

想听的人听 ，不想听的人就别听 。 内核恐慌的网址是 ipn.li/kernelpanic。 我们推荐大家使用 Podcast 泛用型客户端订阅我们的节目 。

如果您不知道什么是泛用型客户端 ， 或者您不知道该用什么客户端 ， 欢迎访问 ipn.li/faq。 同时也欢迎你为我们的节目捐款 ， 捐款地址是 ipn.li/kernelpanic/donate。

捐款金额随意 ， 只要是能被 8 整除的正整数就可以 。 捐款不会为你带来什么 ，不捐也不会让你失去什么 。

我们的口号是 ： No hard feelings.

**Rio** [0:39]
越来越熟练了这一段话 。

**吴涛** [0:41]
耶 ， 对 ， 这是苦练的结果 。 每天晚上含着小石子 ，在洗澡的时候背这段贯口 。

**Rio** [0:48]
嗯 ？

**吴涛** [0:49]
你在练的 。

**Rio** [0:49]
我觉得不是这么耳熟 。

**吴涛** [0:50]
哈哈哈 。

**Rio** [0:51]
这谁来着 ？

**吴涛** [0:52]
我不记得了 ， 反正是某个演说家要克服口吃的毛病 ， 然后 ——

**Rio** [0:58]
这故事真的吗 ？ 还是一个鸡汤文 ？

**吴涛** [1:02]
Good question。 我不知道 ，有可能是真的 。

**Rio** [1:04]
因 - 因为我在想一下， 含着小指指练春花这件事情的意义何在啊 ？

**吴涛** [1:09]
就增加你的障碍吗 ？ 就好像绑着沙包在操场上跑 ， 绑着沙包在操场上跑圈一样 ， 可以让你吐个小石子之后， 发现自己的舌头好像变得灵活了 。

**Rio** [1:22]
所以以此类比的话 ， 如果程序员要提高自己的水平 ， 应该怎么增加这个难度呢 ？

**吴涛** [1:27]
呃 ，不用显示器写程序 。

**Rio** [1:31]
哈哈哈 。 用什么 ？ 那个打孔吗 ？

**吴涛** [1:36]
呃 ， 就 ， 或者降低一点难度 ， 就只用单色显示器写程序 。 然后等你有了语法高量之后， 呃 ， 效率就可以升起来 。

**Rio** [1:49]
所以用什么 ？ 呃 ， 非语法高量的 ——

**吴涛** [1:53]
别用机器 。

**Rio** [1:54]
用用记事本写程序 ？

**吴涛** [1:56]
对 。This is partially true。 我必须说 ， 就是你你不用 IDE 写程序的话 ， 如果你一开始就坚持不用 IDE 写程序 ， 那么等到你又开始用 IDE 的时候 ， 你的效 - 你的效率应该会有成倍的提升

。 是不是这个道理 ？

**Rio** [2:12]
嗯 ， 想来应该是的 。 所以这么说来 ， 我们都算是一直在背着沙包在跑 ？

**吴涛** [2:18]
对 。 Doing it the hard way. 然后当你 do it the normal way 的时候 ， 你就会发现容易了很多 。

**Rio** [2:27]
好吧 。

**吴涛** [2:28]
就好像打星际争霸 ， 先用现在 brutal 下面通个关 ， 然后再回去打 easy。

**Rio** [2:35]
简直小菜一碟 。

**吴涛** [2:36]
没错 。

**Rio** [2:37]
嗯 。

**吴涛** [2:38]
OK， 呃 ， 先进入我们的第一个环节 ，follow up。 呃 ， 我听说 Rio 拿到了一块 Happy Hiking Keyboard Pro R，是真的吗 ？

### HHKB键盘

**Rio** [2:47]
对 ， 那个上次 Lawrence 把他那块闲置不用的 HHKB Pro 2 送给了我 。

**吴涛** [2:55]
这是什么时候的事情 ？ 这是两个月之前的事情吧 ？ 这快递走了这么久吗 ？ 还是 ——

**Rio** [3:01]
啊不 ，是 ，是 。 我是我是挺早拿到 ，但是因为还没来得及 ， 就急于感觉上手嘛 。

**吴涛** [3:06]
OK。

**Rio** [3:07]
所以就也一直没有讲 。 但是就算也用了一段时间了 ， 现在也那个 ，因为那个整个键位啊那些都变了嘛 。

**吴涛** [3:14]
嗯 。

**Rio** [3:15]
嗯 ， 所以还是花了一点时间来适应的 。 现在适应之后觉得 ， 嗯 ， 还不错 。 所以我们可以讨论一下这个你的那个那个 ，其实我有一直有个疑问 ， 好像那个 HHKB 它到底有几个版本 ？

**吴涛** [3:28]
应该是有若干个版本 。 首先它有若干版本 。 呃 。

**Rio** [3:34]
因 - 因为我看那个 Wikipedia 上面写 ， 写的时候它有好 ， 可能有四到四五个 ， 四五六个版本 ， 还有什么 。

但是根据日本的和那个 International 不一样 。 但是包包有那个 HHKB Professional 啊 ，Professional 2。 然后现在我看到那个是在卖的是叫什么 Lite， 对吧 ？

**吴涛** [3:51]
应该是这样的 ， 一开始有 HHKB， 呃 ， 普通版本 ， 就是第一代 HHKB。 后来有了 HHKB Lite， 再后来有了 HHKB， 呃 ，Pro， 呃 ，2。 然后 Pro 2 后面又出了一个 S 版本 ，Ultimum S， 就是加了橡皮圈的比较 ， 呃 ， 降噪版本 。S stands for Silent。

**Rio** [4:15]
所以它们之间有什么区别呢 ？

**吴涛** [4:17]
呃 ，Lite 版本有方向键 。

**Rio** [4:21]
啊 ，OK。

**吴涛** [4:22]
然后， 呃 ， 日语版本是 ， 就是是那种大的 T 形 ，不是 L 形 ， 倒倒 L 形回车的 ， 应该是 。

**Rio** [4:32]
Oh no。

**吴涛** [4:33]
对啊 。 因为 ——

**Rio** [4:34]
所 - 所以它 ， 它所有 ， 就就我们这么说吧 ， 它是分型号和那个国那个国家的 。 就是如果我们不考虑这个国家的区别 ， 只考虑型号的区别的话 ， 它有几个不同 ？

有最 ， 就是 The original，是哪一款 ？ 就最最原始的那款是哪一款 ？

**吴涛** [4:50]
Original 现在应该已经找不着了 ， 就已经不在了 。

**Rio** [4:52]
它停产了嘛 。 但是我想知道那那款应该叫什么名字 ？ 就叫 HHKB 吗 ？ 还是叫什么 ？

**吴涛** [4:57]
应该是就叫 HHKB Pro。 应该是就只叫 HHKB。 然后 Lite 和 Pro 的区分是从第二版才有 。

**Rio** [5:05]
所以 Lite 和 Pro 之间是什么区别 ？

**吴涛** [5:07]
就 Lite 是 Lite 版本 。 哈哈哈 。

**Rio** [5:11]
嗯哼 。

**吴涛** [5:12]
这是一个很有趣的问题 。 呃

，Lite 和 Pro 之间的版本 ， 很有可能键帽是有差别的 。

**Rio** [5:21]
然后那个 Pro 的版本现在是不是已经没有卖了 ？

**吴涛** [5:25]
呃 ， 对 ， 第一代的版本应该已经没有卖了 。 甚至第一代的版本可能是没有 International 版本的 。 就是是一个纯日文的 layout。

**Rio** [5:33]
那因为我们现在用的都是所谓的 Professional 2， 对吧 ？

**吴涛** [5:37]
对 。

**Rio** [5:37]
Pro 2。 然后我去它那个官网看 ， 好像现在这款也没有卖了吗 ？ 还是怎么样 ？

**吴涛** [5:43]
有吧 。 不会停产了吧 ？

**Rio** [5:46]
因为我去它官网 ， 它那官网也很长得很奇怪 ， 就是你不知道它到底是个什么样的 ， 什么性质的网站 。

因为做得很 ， 嗯 ， 很日本网站 。

**吴涛** [5:57]
哈哈哈 。 这个这个描述太抽象了 。 呃 ， 总之反正日本电商网站都不怎么样 。 这是这是肯定的 。

对 。 而且 PFU 甚至不是做电商的 ， 它只是一个 ——

**Rio** [6:07]
没错 。 现在它 PFU， 它它这个这个叫做 Embedded Keyboard， 这个 HHKB 这个页面上只有一款 ， 就是 Lite 2。 就它在展示的只有 Lite 2。

**吴涛** [6:16]
你看的是英文网页吧 ？

**Rio** [6:18]
对啊 。

**吴涛** [6:19]
啊 ， 日文日文内容 ， 日文版本和英文版本不一样 。

**Rio** [6:22]
啊 ？

**吴涛** [6:23]
哈哈哈 。

**Rio** [6:24]
呃 ， 为什么会这样 ？

**吴涛** [6:27]
我不知道 。 也许他们绝大多数用户都是集中在日本 。 我我的这一块键盘实际上是托朋友从日本买的 ， 所以我 ——

**Rio** [6:36]
好吧 。 所以你那款是那个日本版吗 ？

**吴涛** [6:38]
不是 ，是 International 版本 。 就我特别强调说一定要用 International 版本 。

**Rio** [6:44]
好乱了 。 所以你那个是没有方向键 ， 然后只有一个在最右边有一个 Fn key 的 ， 对吧 ？

**吴涛** [6:49]
对 。

**Rio** [6:50]
那跟我那款是一样 ，但你的是无刻印 ， 我的是有刻印的 。

**吴涛** [6:53]
对 。

**Rio** [6:54]
其实 ， 唉 。

**吴涛** [6:55]
一股一股一股优越感油然而生 。

**Rio** [6:58]
哈哈哈 。 键帽可以换是吧 ？

**吴涛** [7:02]
对 ， 键帽可以换 。

**Rio** [7:03]
我要准备买一套无刻印的 ， 接着装逼 。

**吴涛** [7:06]
哈哈哈 。

**Rio** [7:08]
嗯 ， 就你 ， 然后我就看那个官网上那个 ， 现现在在说这个 Lite 2 嘛 。 然后 Lite 2， 刚才你你也不 ， 你你所以你也不知道 Lite 和 Professional 的区别是什么是吧 ？

**吴涛** [7:18]
我怀疑 Lite 所用的那个按下去的那个开关应该不是

Tor-Tor。

**Rio** [7:28]
TorPrate？

**吴涛** [7:29]
TorPrate。 不是 TorPrate 的把 ，不是 TorPrate 的键帽 。

**Rio** [7:33]
所以那它还是所谓的静电容键盘吗 ？ 还是什么其他的一个什么东西 ？

**吴涛** [7:38]
有一定可能 。 因为 Lite 好像卖的便宜 ，而且不是便宜 ，而且而且不止便宜一点吧 。

**Rio** [7:44]
哎 ， 好吧 。 然后那个 1 和就是就是 ， 呃 ， 比如说 HHKB Pro， 就是没有数字 2 的 ， 都是已经停产了是吧 ？

只有 Pro 2 和 Lite 2 在售了 。

**吴涛** [7:55]
对 ， 应该是找不到 。

**Rio** [7:57]
你说这个这个玩意有日文版 ， 这个日文版在哪里啊 ？

**吴涛** [8:01]
呃 ， 我给你找找 。

**Rio** [8:04]
哟 ， 这个我我搜那个 HHKB 的 Wikipedia， 然后它给了一个 official website， 点过来就是这个 。 然后这边只有一款 Lite 2， 什么都没有了 。

就没有其他任何款型 ， 只有在 Wikipedia 的里面那个列表里面能找得到一些在售 ， 那个还还在售的款 。 它有一个 ， 它有个列表 ，有个 end of life 这个列表 ， 就有一堆都是应该是已经停产了的 。

**吴涛** [8:29]
OK。 呃 ，pfu.fujitsu.com。

**Rio** [8:34]
啊 ， 嗯 。 所以现在在售的是 Type s Professional JP， 就是日文版 ，Professional 2，Lite 2， 还有一个 Lite 2 for Mac。

**吴涛** [8:43]
对 。 这个 Professional JP 应该就是第一代的 。

**Rio** [8:47]
呃 ， 然后其他四款都是国际键位 ， 就是所谓的 International layout。

**吴涛** [8:53]
Professional 2，Professional 2 也有 JP 的版本 ， 我没理解错的话 。 然后 Lite 2 也有 JP 的版本 。

**Rio** [9:00]
然后那个 JP 这款的键的位置好像又不一样了 。

**吴涛** [9:07]
呃 ， 就像我说的 ，Professional JP 的是第一代 ， 然后这一代只有日语版本 。 然后这一代的那个下面的空格键非常短 。

呃 。

**Rio** [9:17]
它好像多了好几个什么其他的键 ，不知道是干嘛的 。

**吴涛** [9:19]
对 。 然后从 Professional 2 开始有了 International layout。 呃 ，Lite 2 也有 International layout， 同时也有日语键盘 。

**Rio** [9:29]
好吧 。

**吴涛** [9:29]
对啊 。

**Rio** [9:30]
哎 ， 所以那个那个具体型号我们就不去那个啰嗦了哈 。

**吴涛** [9:34]
嗯 。

**Rio** [9:34]
我问你一件事 ， 那个你觉得那个方向键对你来说有用吗 ？

**吴涛** [9:39]
嗯 ，其实还是有一些用处 。

**Rio** [9:44]
呃 ， 就这么说吧 。 因为那个就我们两个都是 Pro 2 的版本 ，是没有方向键的嘛 。

**吴涛** [9:48]
对 。

**Rio** [9:48]
你在那个非文本输入框的时候怎么去用方向键 ？ 你要用那个 Fn key， 然后按那个叫什么 ， 那那四个键嘛 ， 对吧 ？

**吴涛** [10:00]
对 。

**Rio** [10:01]
你经常这样干吗 ？

**吴涛** [10:03]
呃 ， 还是挺经常的 。 而且我其实右手的小拇指在 ， 右手的小指在有一段时间以来是疼着的 。

**Rio** [10:12]
哈哈哈 。 就按 Fn key 的原因是吧 ？

**吴涛** [10:15]
对 。

**Rio** [10:16]
OK。

**吴涛** [10:17]
而且不止那个 ， 就是在公司里面我把那个 Fn 加上 A 和 S 改 ， 呃 ， 弄成了调节音量大小 。 所以调节音量也要按那两个 。

**Rio** [10:28]
Fn 是可以定自定义的吗 ？

**吴涛** [10:31]
呃 ，Fn 加 A 和 Fn 加 S 在普通 PC 上也是调节音量 ，其实 。在 Mac 上也是 ， 我想想 。 呃 ， 然后然后这个组合 。

**Rio** [10:43]
不对不对不对 。 你你在公司用的是 Linux 系统对吧 ？ 不是 OS X？

**吴涛** [10:46]
对 。

**Rio** [10:47]
因为我上次的印象是我调用那个 Fn 键定义的时候 ， 好像没有按出来有什么 ， 就是 Fn 加个什么 ， 好像不能在苹果那个那个键盘的设置里面调整一些快捷键吧 ？

可以吗 ？

**吴涛** [10:59]
这个不行 。 但是 Fn 加 A， 呃 ， 直接对应了多媒体键里面的 volume up， 如果没理解错的话 。 对 。

**Rio** [11:09]
OK。Good to know。

**吴涛** [11:11]
Yeah。

**Rio** [11:11]
所以 ， 哎 ， 我还可以问你 ， 你这你这个这个怎么查 ？ 在哪里知道有这些对应的关系 ？

**吴涛** [11:16]
呃 ， 你的键 ， 你不是有刻印键盘吗 ？ 你你那个键盘的正下方 。

**Rio** [11:24]
没有啊 ， 没有啊 。在在下在 Fn 就是就就是那个 ， 这么说吧 ，在左手键那些区域上面只有只有键帽顶上才有 ， 没有下没有侧边那个印的那个额外的键的含含义的 。

**吴涛** [11:38]
嗯 。

**Rio** [11:39]
所以我不知道为什么你你知道按 Fn 加 A 和 S 是调音量 。 我从来没有试过 。

**吴涛** [11:44]
因为说明书上有写吧 ， 我记得 。

**Rio** [11:48]
啊 ， 还有说明书 ？

**吴涛** [11:49]
对 。 你是哪来的山寨 ？ 哦哦哦 ，是是李无意直接寄给你的是吧 ？

**Rio** [11:55]
对啊 。 因为是他寄过来 ， 就那个就是没有原装盒子嘛 。 而且 。

**吴涛** [12:01]
这个人， 李无意这点做的太不靠谱了 。 你要是我我一定会吧 。 原厂说明书 。

**Rio** [12:08]
这个这个这个事情不不怪他哈 。 因为因为是是他托家人打包寄的 ， 所以比较麻烦 。

**吴涛** [12:15]
啊 ，OK。

**Rio** [12:16]
就我拿到的时候连那个那个 USB 的线都没有 。 我看那个都是那个通用的一个 ， 呃 ， 应该是不是 Micro mini USB 吧 。

**吴涛** [12:25]
嗯 ， 对 ， 没错 。

**Rio** [12:26]
就还挺常见 。 我就自己配了一根 ， 就还可以 。 但是我不知道还有说明书的这这么一回事 。

**吴涛** [12:32]
是的 ， 它还有说明书 。 而且它说明书里面会写那后面几个跳线 ， 搬到什么状态 ，是什么样的功用 。

**Rio** [12:39]
那个 DIP 可以在网站上查的吧 ？ 但是这个你说这个快捷键是这个东西 。

**吴涛** [12:44]
快捷键应该也能在网上查吧 ？I'm pretty sure。

**Rio** [12:47]
啊哈 ，really？

**吴涛** [12:49]
对啊 。

**Rio** [12:49]
好吧 ， 那我查一下 。 哦 ，OK， 我还看到了这个这个 format。 哎 ， 它是 Lite 2 的话 ， 多了一个 Fn key 在左边是吧 ？

**吴涛** [13:00]
右边的 Fn 还有吗 ？

**Rio** [13:02]
有有 ，也有 。 就但左边又多了一个 Fn。 我这个还蛮有用的 。 就我发现最严重的问题就是 Fn 在右边 ， 然后在那个苹果键盘上 Fn 是在左下角嘛 。

就是说还蛮人格分裂的 ， 一会儿按左边 ， 一会儿按右边 。

**吴涛** [13:20]
嗯 。

**Rio** [13:21]
啊 ， 然后再我再问你哈 ， 就说在这个就是 OS X 的系统的文本编辑框里面 ， 你要换上下行的时候你怎么办 ？

**吴涛** [13:31]
再说一遍 ，OS X 的系统的文本框 。

**Rio** [13:34]
就是比如说在这么说嘛 ，在就是你现在用的是这个 ， 我们用那个 NVAUT 编辑这个 notes 嘛 。

**吴涛** [13:41]
嗯 。

**Rio** [13:42]
你要切换上下行怎么办 ？

**吴涛** [13:46]
用用方向键啊 。

**Rio** [13:50]
哈哈哈 。 然后你要左右移动光标怎么办 ？

**吴涛** [13:53]
呃 ，Ctrl 加 Pn 是可以的吧 ？ 然后 。

**Rio** [13:57]
是啊 ， 那个是 Emacs keybinding 啊 。 但是你你是一个 Vim 用户 。

**吴涛** [14:00]
对 ， 所以我用方向键 。

**Rio** [14:05]
哈哈哈 。 我我我为了这件事情 ，因为方向键不好用嘛 ， 要用那个那个那按 ，其实都是要用小指的 。

左边的话虽然 Ctrl 键也是要用小指 ，在在那个普通键盘的 caps lock 的位置嘛 。 对吧 ？

**吴涛** [14:20]
嗯哼 。

**Rio** [14:21]
呃 ， 然后你要用那个 Ctrl 按着 ， 然后就是 N 是下一行 ，P 是上一行 ， 然后 F 是右移 ， 然后 B 是左移光标嘛 。

然后如果你用方向键的话 ，其实就是用右手的小指按住 Fn， 然后按那几个方向键的附用的键 。

**吴涛** [14:37]
对 。

**Rio** [14:37]
其实是好像是差不多的 ， 我觉得 。

**吴涛** [14:40]
所所以所以你的点是什么 ？ 就是你作为一个 Vim 用户 ， 为了捍卫自己的尊严 ， 所以一定要找到一个 。

**Rio** [14:45]
我我现我现在很分裂 。 因为我一会儿要用 Emacs keybinding， 一会儿要用那个 ， 就是我本质上就遇到这种非 Vim 的 keybinding 支持的情况下， 比如说在这个这个 GUI 界面上， 你选择上下的一个菜单 ， 举个例子 ， 你只只能用这个方向键了嘛 。

**吴涛** [15:04]
对 。

**Rio** [15:05]
这个时候我就只能按住用用一个右手的小指按住 Fn， 然后用方附用方向键去去调那个选择 。 但是在很多文本编辑框里面 ， 我又又在用那个 Emacs keybinding， 比如说在 NVAUT 或者是这个 ， 比如说这个 Safari 的这个地址栏吧 ， 我要编辑它的时候 ， 我又会用那个这个 Emacs keybinding 去去加速我的那个光标移动 ， 比如说可以一个 word 一个 word 的 ，而不是一个 character 一个 character 移动嘛 。

**吴涛** [15:30]
嗯哼 。

**Rio** [15:32]
啊 ， 所以就我最近特别人格分裂 ， 你知道吗 ？ 就在然后在那个 terminal 或者是在 Vim 里面打的时候 ， 又是用的那个 Vim 的 keybinding。

**吴涛** [15:42]
你在 terminal 里面用 Vim 的 keybinding？

**Rio** [15:45]
啊哈 。

**吴涛** [15:45]
你是说你的呃 ，line edits 用的是 Vim 的 keybinding？

**Rio** [15:50]
对啊 ， 对啊 。

**吴涛** [15:51]
我已经把 line， 呃 ，line edits 的 keybinding 就是改回默认的 Emacs keybinding。

**Rio** [15:58]
Emacs 的嘛 。

**吴涛** [15:58]
对 。

**Rio** [15:59]
所以你你你也叛逃了 。

**吴涛** [16:01]
不不 ， 我不是 。 对 ， 就是主要是向现实妥协吧 。 就是当因为一天要连无数台 remote， 呃 ，session 的话 ， 就 SSH 到其他的机器上的话 。

**Rio** [16:15]
不想每次都改 。

**吴涛** [16:16]
不想每次都改 ， 对 。 而且去用别人的键盘的时候也会非常的痛苦 。

**Rio** [16:24]
好吧 ， 理解了 。 所所以总体来说 ， 这个 HHKB 那个 Pro 2 你用起来用你用了多久了到底 ？

**吴涛** [16:33]
一年多吧 。

**Rio** [16:34]
所以感觉如何 ？

**吴涛** [16:36]
我也不知道 。 我我觉得它已经内化了 。 就是你不说的话 。

**Rio** [16:39]
不觉得它是一 ，不觉得它是一个什么事了是吧 ？

**吴涛** [16:42]
对 ， 现在我已经不觉得它是一个 。

**Rio** [16:43]
因为我因为我刚用一个月嘛 ， 所以感觉还不太一样 。 就是有时候会觉得咦 ，有点人格分裂 。 因为我还有是还用那个笔记本的那个 Mac 自带那个键盘嘛 。

**吴涛** [16:52]
呃 ， 对 ， 我也是 。 而且我的两个 layout 是不一样的 。

**Rio** [16:56]
所以我其实我在想那个他们他现在在卖那个 Lite for Mac， 那个感觉可能稍微正常一点 。

**吴涛** [17:02]
所以要买一块吗 ？

**Rio** [17:04]
哎 ， 再想再说吧 。 这个先先适应一段时间 ， 再再说看看到底能不能够接受这种方式 。 不过我觉得整个手感还是不错的 。

这个 TorPrate 的那个按键的感觉还是噔噔噔 ， 这种比较噔噔噔 ，duang duang 的感觉 。

**吴涛** [17:18]
哈哈哈 。OK。

### 读者来信

**Rio** [17:22]
好 ， 呃 ，不 ，不扯这个单 。 嗯 ， 那今天我们进到下一个环节吧 ， 读两封这个听众来信 。

**吴涛** [17:30]
对 。

**Rio** [17:30]
第一封你来吧 。

**吴涛** [17:32]
呃 ， 好 。 对 ， 这两封来读的来信都是针对上一期那个我我独白的那一期 。

**Rio** [17:38]
你的独白 。

**吴涛** [17:39]
对 。 哈哈哈 。 呃 ， 这个反正事后这个不鸟万如一和不鸟万 Rio 先生都表达了惊讶 ， 说你一个人嘚啵嘚嘚嘚居然可以嘚啵一个小时， 这个真的我自己也没想到我可以嘚啵一个小时 。

但事实上我本来是计划嘚啵两个小时的 。

**Rio** [17:58]
哈哈哈 。 呃 ， 我觉得已经很厉害了 。

**吴涛** [18:03]
OK。 谢谢 。 首先是我们的老朋友 Virgil Minh 先生 ，是先生吧 ， 寄来的 ， 或小朋友 ， 对 ， 寄来的一封听 ， 呃 ， 听众来信 。

**Rio** [18:16]
嗯哼 。

**吴涛** [18:16]
吴涛您好 。 呃 ， 这是对新鲜出炉的第 18 期节目的反馈 。 对 ， 我记得这一期应该是在上线之后可能五六个小时 ，他就写了一封 ， 写了这封信来 ， 真是太热情了 。

嗯 ，他说高级程序员到汇编到可执行文件到机器指令这一系列过程并不算是编码吧 ？compile 和 encode 是两回事 。

这个 ， 呃 ， 对 ，其实我之所以说自己本来计划计划说两个小时， 就是因为我后一个小时是要说编码的 。

但是说到一个小时的时候已经就撑不住了 。 呃 ， 前前前一部分是说 compile， 就是说计算机的指令是怎样转换为二进制指令的 。

**Rio** [19:07]
嗯哼 。

**吴涛** [19:07]
计算机的文本指令是如何转换为二进制指令的 。 然后我本来计划在后半部讲这个编码 ， 就是什么 Unicode 呀 ，ASCII 啊 ， 乃至什么 GV blah blah 一系列 。

但是后来实在是撑不下去了 。

**Rio** [19:25]
哈哈哈 。

**吴涛** [19:26]
嗯 ， 所所以才会有给人这种印象 。 对 ，其实上一期的真正的主题的确是编码 ， 只不过没能进入真正的主题而已 。

**Rio** [19:36]
这叫什么 ？ 戛然而止 。

**吴涛** [19:39]
对 。

**Rio** [19:40]
面对那个字了 。

**吴涛** [19:42]
接着读 。 有一件事情让我有些感叹 ，ASCII 编码里面大写字母的 A 是 65， 这件事情存在我记忆里面应该已经 10 年了吧 ， 然而直到今天我才明白那是 64 加 1。

当年只是把 65， 当年只是把 65 作为一个 magic number 强行记住而已 。 因为当时刚刚学二进制 ， 对此丝毫不敏感 ， 老师也没有多解释 ， 我也没有觉得有什么不对 。

然而现在看来明显是少了一块拼图 。 以此类推 ， 小写字母 A 是 97，97 就等于 64 加上 32 加上 1，也是很符合逻辑的 。

对 ， 所以 ， 呃 ， 这里就是他的意思就是 64 这个数字就是七 ， 呃 ， 八进制啊 ，不是八进制 ， 二进制的七位的 1， 然后后面跟 6 个 0， 所以这是一个特别的数字 。

然后 97 是 64 加 32，也就是 1 后面 6 个 0 加上 1 后面 5 个 0，也就是 100000， 这个数字是 60，是 96。 然后 96 后面的第一个就是啊 ，100001， 这个二进制编码是代表小写字母 A。

所以这些其实在最开始规定 ASCII 的时候 ，ASCII 码的时候都已经都是都是有一定的内在逻辑的 。 对 。

**Rio** [21:06]
嗯哼 。

**吴涛** [21:07]
然后然后 ASCII 码的这个 64 呢 ， 就是 at。 所以所以各位如果你要想去铭记某一个事件的时候 ， 你可以多拉几个 at， 然后前面可以加上一个大写字母 Y。

**Rio** [21:21]
哈哈哈 。

**吴涛** [21:22]
OK， 接着读 。 呃 ， 这让我想到另一件事 ， 大一的科学家课程里面有一道习题 ， 实现一个支持 Reverse Polish notation 的计算器 。

当时也没觉得有什么特别之处 ， 无非就是个循环练习嘛 。 为什么要弄出这么一套反直觉的记法呢 ？

直到两年之后上到 Functional programming 课 ， 到呃 ， 快到期中考试的时候才突然反应过来 ， 这无非就是换了个形式 ， 针对四则运算这个非常特别的情况 。

呃 ， 显然显示的把递归优化成循环 。 而 Reverse Polish notation 发明早于 LISP 二三十年， 我也没读 LISP 最早的那篇论文 ，但我相信两者形式上相通 ， 绝不只是偶然 。

这种感觉我不知道怎么形容 ，Deju Vu 吗 ？ 如果在一开始学习的时候就能了解背后这些神秘的东西 ，Computer Science 本来应该可以更迷人。

至于你的节目里面只有一分钟不到的正题 ， 省略省略几百字的吐槽 ，但我有但有一点我想说明 。

这么说吧 ， 我们括号 ， 仅指我自己周边的人， 我生于 1992 年 。 括号结束 。 这就是为什么我说他是个小朋友 ，1992 年啊 ， 天呐 。

**Rio** [22:46]
90 后的明先生你好 。

**吴涛** [22:48]
对 ，90 后的明小朋友你好 。 嗯 ， 接着念 。 我们生长起来的环境里面并没有什么机制来保证人们人们在生长过程中能够以较温和的方式了解如何谈恋爱这个常识 。

独生子女和父母离婚成风 ， 括号 ，90 年代人们突然像赶时髦似的开始考虑甚至执行离婚 ， 括号结束 ，但影响就不提了 。

我可以确定的是 ，在大学之前三观尚未定型的时候 ，在国内练习谈恋爱的机会不仅是少 ，而且大多数情况下是离经叛道 ， 得不到任何可靠的第三方支持的 。

于是等到上了大学之后， 我听到看到了许多不知道该称为悲剧还是黑色幽默的故事 。 我自己也括号 ，不知道有幸还是不幸 ， 括号结束 ， 参与了其中一个 。Learn it the hard way 的确是有效的策略 ，但是如果我们讨论的是感情呢 ？

这里的 hard way 可能对你或者对对于对方造成不可逆的伤害 。 真的没问题吗 ？ 更重要的是 ， 最好的时机已经过去了 ， 这个 bug 改起来会非常痛苦 ， 近乎于不可行 。

这不只是程序员的问题 ， 我承认外行人甚至业内人士对于程序员的 stereotype 有时候不可理喻 ，但问题的本质仅仅是作为一个人如何发展 、 处理和另一个人的亲密关系而已 。

把职业甚至相关的 stereotype 卷进来作为预设处理 ， 难道不是缘木求鱼吗 ？ 最后， 你为什么要一次性录完呢 ？

不能休息一天接着录吗 ？OK， 念完了 。Rio 有什么想说的吗 ？

**Rio** [24:31]
嗯 ，其实我觉得他对对对你上期的打引号的正题的诠释挺好的呀 。 就是这个真的是一件跟职业啊什么其他关系不大的事情 ， 这就就是一个做人的基本的基本的一些东西 。在我们现在这个 ， 我很好 ， 我很这个社社会的一个欠缺吧 。

但是我觉得很神奇的是 ， 哎 ，90 后现在谈恋爱还是这么受限吗 ？

**吴涛** [24:56]
对 ， 我有这种感想 。 就是我觉得 80 我们我们这支 80 年代后的这一批人啊 ， 这次 Rio 你逃不掉了 ， 你好歹是个 80 后 。

呃 ， 我们在年轻的时候谈恋爱也很受限制 ， 这个是这个是实情 。 但是我怎么觉得好像好像 90 后应该不存在这样的限制啊 。

难道难道是中国还是那个样子吗 ？

**Rio** [25:22]
呃 ， 作为两个外国生活在外国的人， 怎么说真的是 。

**吴涛** [25:32]
是吗 ？

**Rio** [25:33]
对 ， 我我觉得我们觉得我不够了解他们 ， 就不不够了解这个后一个十年出生的人 ，他们的一个成长的状况 。

这个是挺挺讨厌的一件事情 。

**吴涛** [25:43]
嗯 ，不过可能也可以理解 ，因为你想我们毕业的时候 ， 带我们的那些老师至少还会在教职上， 对 ， 至少还会在教职上再待个十年吧 。

所以 ， 嗯哼 ，也许现在的谈恋爱的环境没有我们想象的那么开放 。

**Rio** [26:05]
或者这么理解 ， 就是只要高考这件事情还存在 ， 就只要还中国还是这么一种这种就是说呃 ， 人多的竞争的模式 ， 可能这件事情就很难幸免 。

**吴涛** [26:18]
嗯

，有道理 。

**Rio** [26:21]
哎 ， 说到高考 ， 好像是昨天还是前前几天刚刚高考结束吧 。 不知道我们听众朋友里面有没有正现在是属于解脱呢 ， 还是什么一个状态呢 ？

**吴涛** [26:34]
或者是刚刚考完打算报计算机系 ， 您千万别啊 。

**Rio** [26:38]
哈哈哈 ， 三思哦 。

**吴涛** [26:41]
对 。

**Rio** [26:42]
你得想清楚 。

**吴涛** [26:43]
嗯 。

**Rio** [26:44]
好吧 。

**吴涛** [26:45]
然后我觉得他说的那个程序员的 stereotype， 就是我其实上一期我已经不记得自己说了什么了 。

**Rio** [26:54]
对 ， 我你上一期我觉得有一句有一点 ， 就是我觉得就他这里也有也有也有提到嘛 ， 就是说这件事情跟职业真的没有太大关系啊 。

**吴涛** [27:03]
对 ，其实我上一期之所以会想到这个 ， 就是因为呃 ， 可能是在网上看到哪个帖子 ， 说什么我是程序员 ， 找不到女朋友 blah blah 的 。

**Rio** [27:12]
嗯哼 。

**吴涛** [27:13]
或者是什么我男朋友是程序员 ， 我想要送他一个什么什么什么什么玩意儿 。 然后我总是在想说程序员这个身份有那么重要吗 ？

呃 ， 为什么要把这个身份特单独提出来 ， 好像它 somehow someway 就改变了你是一个

人这一个基本呃现实一样 。

**Rio** [27:37]
不 ，有可能是跟你以前有一次说到这么一件事情有关系 ， 就是编程其实是一个逐渐异化的过程嘛 ， 就是抛掉你作为人的那一面 ， 然后嗯 ， 要要把你假设成一个很理性的机器 ， 去一行一行去解析执行那段代码的这么一个过程 。

然后所以我不知道是不是时间长了之后会让人变得非

， 非人类 ， 变得过于理性和非人类 。 对 ， 然后有很多这个所谓中国国内的这种教育出来的那种理工科生会 ，有个字叫什么 ， 特别轴 ， 你知道吗 ？

就认死理就不知道怎么变的 。

**吴涛** [28:17]
经常会把我我们理我们理科生挂在挂在嘴边 。

**Rio** [28:21]
没错没错 。 然后这个时候就最容易在感情上出现问题 ， 就是说你觉得逻辑上事情是成立的 ，但是你要知道这个世界并不是按照逻辑的方式运行的呀 。

**吴涛** [28:31]
对 ， 这件事情可能会让很多人感到伤感 ，但现实就是在现实世界里面 ， 如果你把一个 condition 测试 1 万遍 ， 那可能有 5,000 遍是 true， 另外 5,000 遍是 false， 你你得不到一个确定的结 。

而不像程序里面 ， 我们接下来要接触的主题 ， 就是有些事情是可以重复的 ，有些这重复的事情就是可以被测试的 。

但现实生活里面很多这些东西是没有办法重复验证 ，也许你再来一次 ， 嗯 ， 得到的结果就会完全不一样 ， 谁知道 。

**Rio** [29:07]
甚至就说他们经常说的那句话嘛 ， 两点之间的最最短的线路可能不是直的 ，但这句话你怎么理解 ， 你自己去想啊 。

**吴涛** [29:14]
对 ， 取决于你怎么定义的最短 。

**Rio** [29:17]
嗯哼 ， 可能最省时间而已 。 哈哈哈 。

**吴涛** [29:20]
对 ， 这就好像一个 GPS 导航仪会问你 ， 你是要最省时间呢 ， 还是要最短的线路 ？

**Rio** [29:25]
嗯哼 。

**吴涛** [29:26]
刚刚学开车的时候 ， 我想说这两者难道不一样吗 ？ 后来才明白真的不一样 。

**Rio** [29:34]
而且我觉得对于很多这个就是程序员也好 ，他的可能你很多人的职业规划是说要在几年， 三五年、 十年之后做成一个所谓的技术岗位的管理者这么一个 。

对 ， 这这个时候其实你会发现 ， 你一旦走向所谓的管理岗位 ， 你是你要写代码的时候就不多了 。

这反而是考验你对这个人的理解 ， 对人性的思考的地方会比你逻辑的地方多的地方那个多了多的时候 。

所以 ， 嗯 ， 你如果处理不好你和你亲密的人的关系 ， 估计你走管理岗位也会挺郁闷的 。

**吴涛** [30:14]
对 ， 你会发现自己此前一直努力压抑的情商忽然变得无比重要了 。

**Rio** [30:19]
哈哈哈 ， 觉得自己就是这个白痴一样在那里 。

**吴涛** [30:23]
对 。

**Rio** [30:24]
当然说到最后这个事情 ， 那我们可以反正你上次你也吐槽了嘛 ， 那我也我也来吐槽一下， 就是反正我找女朋友是我当成因为程序员之前的事了 ， 后面怎么着我也管不着了 。

**吴涛** [30:38]
哈哈哈 ， 赤胳膊的炫耀 。

**Rio** [30:40]
哈哈哈

。 好吧 ，OK 啊 ， 我们讲那个下一条的这个听众反馈 ， 这是一封来自于一位叫

Flilly 徐 ， 应该是徐 。 对 ， 我不知道这个是微托马拼音吧 ， 应该是 。 对对 ，他说 ， 哎 ， 我不知道是不是 Podcast 客户端有问题 ， 或者是你们的 Podcast 发布服务器有问题 ， 总之有一段时间当我下载 《 内核恐慌 》 并打开来收听的时候 ， 会传出一个很好听很温柔的女声说 ：" 大家好 ， 欢迎收听流行通信第 XX 期 。

我并不知道 IPN 还有另外一档叫做流行通信的节目 ， 我多次以为只是两位主播受不了之前许多没有主题 、 中心重点和深度的 softcore 讨论 ， 终于找来了哪一位美女大牛进行一个高级讨高级话题的讨论 ，但是后来我才意识到原来是下载错了节目 。

再后来当我看到录音的时间短于一个小时的时候 ， 我就会本能的以为 Podcast 又出问题了 ， 然后删除重新下载 。"

啊 ， 这个事情在 IT 公论里面其实我有次已经提到过了哈 ， 就是这是一个 bug not a feature。

**吴涛** [31:49]
对 ， 这是我们的 Podcast 发布服务器有问题 ， 或者是对 ，但是但是这个 bug 的成因我到目前为止都没有找到 ，因为我没有办法重现它 。

我们应该在这里发动广大的程序员听众 ， 帮我们测试一下 。 如果你遇到这个场景 ， 请千万去 somehow someway trace back 一下这个这个网址是怎么来的 ， 它经过了哪些路由 ， 它它是到底是怎么一回事 。

**Rio** [32:15]
对 ， 我我因为我因为我现在想了几个可能出现问题的地方 ， 一个是我们的自己那个 IPN 的那个 CMS 有问题 。

**吴涛** [32:22]
对 。

**Rio** [32:22]
但是我没我我但我也我做了很多测试 ， 这个是今天我们的后面的主题啊 ， 一会再说 。 我做过很多测试啊 ， 就是我完全没办法重现这件事情 。

然后我就是我就想着说 ， 那是不是这个所谓运营商的劫持 ，但现在看来又不是一个非常确定的东西 ，因为有有不同的人在不同的网络环境下， 不同运营商他都遇到类似的问题 。

而且这个事事情似乎是一个怎么讲 ， 就难以预测规律的东西 ， 就我不知道到底是为什么 。 然后之前又是考虑说是不是因为这个啊墙的问题 ，因为我们的服务器在国外 ，但是后来找了一些朋友测试之后也没有得出一个确定结论 。

所以到目前为止这是一个叫什么 phantom bug。

**吴涛** [33:04]
对 。

**Rio** [33:06]
隐虫 。

**吴涛** [33:07]
哈哈哈 。

**Rio** [33:08]
啊 ， 就是它一会出现一会不出现 ， 你也不知道它什么时候出现 ，以及它在什么情况下会出现 。

所以我也很郁闷 。OK， 这是一个声明啊 ， 大家如果有能够帮助我们这个除一下虫 ， 我万分感谢 。

**吴涛** [33:23]
对 。

**Rio** [33:24]
然后接着念这个呃 Flilly 的来信啊 ，他说而这次我重新下载了三次 ， 发现节目的长度依然只有 59 分钟 。

我发现原来这一次没有下错 ， 节目真的只有 59 分钟 。 所以少了那么那么那么多内容和水分 ，是因为少了一个人吗 ？

对啊 ， 正常嘛 ， 我们两个人一人加一碗水就是两个小时 。 如果只有一个人打个对折 ， 差不多 。

哈哈哈 。OK。 好 ，他说以上只是一个玩笑 。 嗯 ， 接着说哈 ， 关于机械键盘的手感是玄学的观点 ， 感觉非常扯淡 。

我用过各种键盘 ， 我长时间使用过红轴和黑轴 ， 薄膜键盘也用 ，而现在主要使用的是 Rio Force 的静电容键盘 。在我身边喜欢薄膜键盘的人也不少 ，他们不喜欢机械键盘的手感 ，但是对于薄膜键盘的不好 ，他们非常清楚 ， 就是在薄膜键盘老化的时候 ， 按键无法回弹或者回弹缓慢 ，而这就是让人们对薄膜键盘手感感觉不好的原因 。

哎 ， 真的是这样吗 ？ 我我不太清楚 。

**吴涛** [34:28]
应该是没错吧 。

**Rio** [34:30]
OK， 接着念 ， 我们平时所说的薄膜键盘 ，是依靠底部的这个碗状硅胶进行回弹的 。在一些键盘中还会还会辅助利用到一些机械结构 ， 比如最知名的笔记本电脑使用的 X 结构 ， 就是叫做 Seizors switch， 对吧 ？

**吴涛** [34:46]
对 。

**Rio** [34:47]
剪刀脚 ， 对 ，但是硅胶碗的寿命根据键盘质量在几十万次到百万次不等 ， 不同键盘的使用寿命也不太一样 。

但是必须承认 ， 新买回来的薄膜键盘手感是非常好的 ， 之所以不选择它 ， 就是因为你很可能在几个月之后， 这些按键就不能回弹 ， 甚至回弹缓慢了 。

这时这个时候的手感就很糟糕 ， 这样缓慢的回弹是我们的手指可能需要自己费力抬起来 ，而不是放松之后被按键推上来 。

这种细微的变化会被手指敏敏呃敏感的察觉到 ，而抬起手指的力气也会比按下按键更费力 。 而在按键无法彻底回弹的时候 ， 就是按下按键的心情会变得烦躁不安 。其实这也说明了为什么这么多人喜欢 Rio Force 和 HHKB 这类不是键盘 ，不是不是机械键盘的高级键盘 ，因为静电容键盘的原理 。

**吴涛** [35:42]
不是薄膜键盘的高级键盘 。

**Rio** [35:43]
呃 ， 对 ，因为静电容键盘的原理和手感跟普通的薄膜键盘太相似了 。 静电容键盘内部是一个橡胶碗 ， 里面是一个碗形的弹簧 ， 所使用的橡胶的寿命要高于普通的硅胶 ，并且里面的碗形弹簧不仅是用来改变电容触发按键 ， 还可以帮助回弹 。

所以静电容键盘的感觉像是回弹有力 ，并且永远是新买回来状态的薄膜键盘 。 嗯 ， 这其实跟我刚刚讲的那个 HHKB 的那个有一段有点关系啊 。

**吴涛** [36:15]
对 。

**Rio** [36:15]
因为我的感觉就是我第一次 ，因为之前我们讨论过键盘那期的 HHKB 静电容键盘 ，但是我自己从来没有用过 ， 就直到上次那个 Lawrence 把他那块机给我 ， 我我当时第一次拿到的时候 ， 感觉还是蛮特别的 ， 我说哎 ， 这个手感 ，因为它并不像我预期的那种机械键盘那种很硬朗的感觉 ，而是一种比较 。

**吴涛** [36:34]
OK， 你刚才念对了 ， 它它原文的确是 Rio Force 和 HHKB 这类不是机械键盘的高阶版 。

**Rio** [36:41]
OK。

**吴涛** [36:41]
对 ， 它漏写了机械两个字 ，但是你的你的解读应该是正确的 。

**Rio** [36:46]
对 ， 我理解是这么理解的嘛 。 所以所以其实这个我觉得就挺挺有意思嘛 ，因为呃 ， 这个静电容的手感真的是很难形容 。他说是这个薄膜键盘 ， 我觉得也不太像 。

我没有用过任何一款薄膜键盘是是这种感觉的 。

**吴涛** [37:02]
对 ， 没错 ， 就是机械键盘你会有明显的那种咔嚓的感觉 ， 就是你会感觉到自己在按一个弹簧一样的东西 ，但是在静电容键盘里面 ， 这种感觉被淡化了 。

你能感觉到自己没有在按一个薄膜 ，但按下去也肯定不是弹簧 。

**Rio** [37:22]
对 ， 所以这件事情我觉得真的就像很多这个东西越来越多的实体物件一样 ， 你光听描述是没有用的 ， 除非你自己真的按上去那一天 ， 或者说甚至说除非你要连续使用相当长一段时间 ， 你才能感觉到这种细微的差别给你的手感 ， 给你的工作带来上什么样的一种影响和变化 。

呃 ， 所以这里就不再多说了哈 ， 大家有机会去摸一下吧 。

**吴涛** [37:44]
对 。

**Rio** [37:44]
啊 ， 接着念这个 ，他后面还有一些一大段的反馈哈 。 嗯 ， 对于这对于这一期主题的编码 ， 我觉得主播在答案周围转了一圈 ， 甚至延伸扯到了指令集以及三进制这些更无关的其他东西 ，但是始终就没有说到底到底什么是编码 。

主播已经提到 ， 比如说我们能看到文字 ， 我们能听到声音 ， 比如说各位现在听到的 Podcast， 我们能看到图片以及一些高雅的小电影 ， 这些东西都不是 0 和 1，不是吗 ？

如何用 0 和 1 表示这些东西就是编码 ，而用这些 0 和 1， 或者说数字 ， 或者说更准确的说是用整数表示文字 ， 那么就是文字编码 。

用来表示音乐就是音乐的编码 ， 比如 MP3、WMA 之类的 。 为了让本来只能表示一二进制数的计算机能够处理文本 ， 就必须将文本变化为相应的数字 ， 这种对应于文本的数值就成了文本编码 。

这段话是在松本幸鸿 ， 这谁啊 ？

**吴涛** [38:44]
松本幸鸿是一个日本的程序员 ， 好像我记得他很自学成才还是怎么着 ， 写了几本书 ， 对 。

**Rio** [38:51]
这段话是在松本幸鸿在他的书 《 松本幸鸿的程序世界 7.1.1》 这个章节里面 ， 早期文字编码中对于文字编码的描述 ， 这大概算是一个非常简洁而且易懂的描述吧 。

**吴涛** [39:06]
我也是才看 ， 松本幸鸿就是 Mats。

**Rio** [39:09]
啊 ，Ruby 那个作者是吧 ？OK， 我一直没反应过来 ， 我就是看他名字特别眼熟 ，但是我不确定到底是谁 。

**吴涛** [39:15]
啊 ， 我把他跟另外一个日本 。

**Rio** [39:17]
所以他日文名字怎么念 ？Mats 什么 ？

**吴涛** [39:20]
Yukihiro Matsumoto。

**Rio** [39:24]
Matsumoto。

**吴涛** [39:25]
Matsumoto Kablo。

**Rio** [39:27]
OK， 嗯 ， 接着念哈 。此外这本书中还介绍了一些很有历史但是又很奇葩的文字编码 ， 如定义了半角片假名的标准 JIS X0201，以及一种类似 ISO 8859 的方法实现 ，但是 ASCII 部分以这个这个叫什么来着 ？

日元符号 ， 日元符号或者是人民币符号 ，因为都是一个吧 ， 就是那个阳少一横啊 ， 替代了反斜杠 ，以上划线替代了这个波浪号 。

**吴涛** [40:02]
阳少一横 ， 太有趣了 。

**Rio** [40:05]
对嘛 。

**吴涛** [40:06]
不是吗 ？ 这就是那个日元的那个印外印 ， 上面打了两横嘛 。

**Rio** [40:11]
人民币也是用它呀 ， 对吧 ？

**吴涛** [40:13]
人民币直接版 。 对 ， 我一直好奇为什么反日这个反日分子从来没有拿这个符号开刀呢 ？ 这个号符号是人民币完全搬迁日元的 ， 你看人卢布都有自己的符号 。

**Rio** [40:26]
所以我我应该用阳嘛 ，他们比他们还多一横 。

**吴涛** [40:29]
对 ， 没错 。

**Rio** [40:31]
当时不打 ， 下下次我们不打人不打那个阴的 ， 我们打阳 。

**吴涛** [40:36]
对 。

**Rio** [40:38]
另一个编码则是奇葩的 ISO/2022， 这种单词因于 193 年的神奇编码方式 ， 使用了类似于编程语言中引号或者注释的方法 ， 通过一个特殊的引号 ， 将 ASCII 编码和其他语言的编码 ， 如汉语的 GB24312 和日语的 JIS X0208 引起来 。

也就是在 ASCII 编码的文本当中， 当遇到三个特殊字符 escape、dollar sign 和 b， 则后面的内容开始切换到 JIS X0208 编码 。 当遇到另外三个特殊字符 escape、 开括号 b， 又切换回呃 ASCII 编码 。在我看到这本书的时候 ， 我不禁感叹原来人类还设计过如此愚蠢的编码 ， 相比起来 UTF 系列真是不知道高到哪里去了 。

**吴涛** [41:28]
哈哈哈 ，是啊 ， 没错 。

**Rio** [41:30]
哎 ， 所以他那个都不叫那个 ， 就最后那个填上 ISO/2022， 这个都已经不算是一个编码方式 ， 它就是一个怎么讲 ？

**吴涛** [41:39]
Escape 方式 ， 规定了一组规则 ， 告诉你在这个时候可以插入其他编码的东西 。

**Rio** [41:46]
这感觉好像写在写 XML， 对吧 ？

**吴涛** [41:48]
对 。

**Rio** [41:49]
开括号 ， 关括号 。

**吴涛** [41:51]
对 ， 它是一种元编码 ， 关于编码文本 。

**Rio** [41:54]
不过其实这个方式在那个 UTF 里面也实现过 ， 上期我记得你也聊到吧 ， 那个叫做这个叫什么 pair 的 ，segregate pair。

**吴涛** [42:03]
呃 ，what？

**Rio** [42:06]
你们你们提到我还是 ？

**吴涛** [42:07]
我没有提到 segregate pair。

**Rio** [42:08]
就是在那个 UTF-16 这个编码 ，因为 UTF-16 是固定两个字节的嘛 。

**吴涛** [42:12]
对 。

**Rio** [42:12]
但是 UTF 的 Unicode 那个那个平面 ， 那个总的字符数是远远超过 16 个字节可以容纳的嘛 ， 所以怎么在 16 个字节这种定长的编码里面装超过 16 个字节那些东西怎么办 ？

**吴涛** [42:25]
对 ， 我没有提到这个 。

**Rio** [42:27]
你没提到这个 ， 那我可以稍微解释一下这个 。 我之前做研究的时候写过这么一段小笔记 ， 就是说那我们必然有一个有一个办法要用多于 16 个字节 ， 就两个 byte 的方式来编码其他东西嘛 。

所以它在它定义了一个特殊的一个一个 ， 就有一有一个范围的字节 ， 只要那个字节开始的时候 ， 它会进入另外一种 ， 就是非定长 16，16 不是 16 字节 ，16 个 bit， 两个字节这种模式 。

刚才说错了 ，不是 16 个字节 ， 那也太长了 ，16 个位 ， 就是两个字节这种方式 ， 就有有一些特殊组合的这个那个两个 byte， 它会定义说从这里开始我们进入另外一种模式 ， 然后另外还有一些特殊的这个两个 byte， 它会说从这里开始我们结束那个特殊模式 ， 回到那个正常的 UTF-16 的编码 。

这种特殊的这种 byte 就叫做 segregate pair， 叫做什么代理组和代理对 ， 就其实跟那个这个 ISO 的 2022 的方式差不多了 。

那你但你不得不说 ，在当时的这个物理史 ， 就是 UTF-16 应该是在 90 年代中后期实现的嘛 ， 这个开发出来 ， 就在在那个当时的历史情况下， 只用两个字节来处理这个 ， 就可能应对绝大部分的所谓的主流的文本 。

因为在当那个时代能够用到计算机进行文本处理的 ，也就是所谓一些发达国家呀 ， 大国这种 ， 像那些小国那种非常不起眼的文字 ， 就已经无暇顾及 ，也无所谓 ， 对吧 ？

**吴涛** [43:56]
我觉得那个时候还是主要为了应对东亚语言 。

**Rio** [44:00]
对啊 ， 那个时候东亚市场 。

**吴涛** [44:02]
刚需嘛 。

**Rio** [44:02]
对 ， 东亚市场呃振兴的非常快 ， 然后微软为了切入这个市场 ， 就不得不采用了这么一个 。

**吴涛** [44:10]
对 ，而且就是也是一个比较临时的方案 ，但是那个时候做出的技术选择 ， 对我们今天来说其实影响非常深 。

**Rio** [44:17]
影响是非常深的 ， 对 。

**吴涛** [44:18]
UTF 如此愚蠢的东西 ， 真的 ， 这是 Windows 上又一个痛点 ，并不得不承认 。

**Rio** [44:26]
没错 ，因为当时在我的我有那个笔记里面有写到过 ， 至少是在我想想 ， 应该是在 Windows NT 的内核是默认是这个 ， 哎 ，不是这个 ，不是 UTF-16， 它是叫 UCS2 这么一个方式来的 。

**吴涛** [44:39]
嗯哼 。

**Rio** [44:40]
就是 UTF-16 其实是 UCS2， 就是刚刚讲 ， 就是所有东西都是两个字节的 ， 没有没有额外的情况 。GDDF-16 是这个 UCS2， 再加了刚才我讲那个那个叫做 segregate pair 的方法去编码超过那种 ， 就是超过那个就是 OXF 四个 f 这么一个段的更高的点位的那些字 ， 对吧 ？

但其实就是 UCS2 这种方式 ，在很多这种编操作系统里面也好 ，不过那个 NT 的那个那个那款 ， 我记得 NT 的那个默认的文件路径是用 UCS2 来实现的 ， 然后像那个 Java 是一点几吧 ， 到 1.5 之前 ，1.6 之前都是用的这个 UCS2 的方法 ， 只是到那个 Java 1.6， 应该是还是 Java 5。

**吴涛** [45:29]
Java 1.2， 一直到 1.6 之前应该都是这样 ，1.7 后面我不知道怎么办 ， 反正 。

**Rio** [45:34]
它在换 UTF-16 嘛 ， 才有可以用那个 segregate pair 的方法来实现 。

**吴涛** [45:37]
对 。

**Rio** [45:37]
然后 Python 也是 ，Python 就 Python 2.2.2. 不管什么版 ， 全部都是用的这个 UCS2，UCS2 或者 UCS4 的方法来表达 Unicode， 就它连那个 UTF-16 都没有 。

**吴涛** [45:49]
对 ， 真是 。

**Rio** [45:50]
所以其实你会看到这这种编码的选择 ， 对后世的影响还是非常深远的 。 当然我们日常可能觉得哎 ， 我怎么没有遇到 ， 那是因为你出的文本还不够奇怪 ，不不足以就不够奇怪 。

**吴涛** [46:04]
没有用过 Windows 的这个和字符串相关的一些 API， 每一个这些 API 每一个都有两个版本 ， 一个是 A 版本 ， 一个是 W 版本 。A 代表说它可以处理 ASCII 编码 ，W 版本说它可以处理这种所谓宽字节的 。

**Rio** [46:19]
Wide character。

**吴涛** [46:20]
这是一个 giant what the fuck，但是有什么办法呢 ？ 谁叫人家商业上成功呢 ？

**Rio** [46:29]
就是 legacy 嘛 。 所以其实我们要往这种 future compatible 方法的话 ， 大家还是尽量使用 UTF-8 这种比较通用的方式来实现 。

虽然说可能 UTF-8 我觉得可能很多人反对它的 ， 这是一个效率的原因 ， 它不是定长的嘛 ， 对吧 ？ 它要是一个变长的 ， 所以处理起来效率可能会比较低 。

但我觉得在现代的这种计算机的处理器的形态来说 ， 这点完全不是问题 。 而且而且有点还有一个抱怨 ， 就是 UTF-8 因为它那个编码方式的原因 ， 它的这个就编码非 ASCII 的时候的效率不高 ， 特别是编码东亚文字的时候 ， 可能效率比较低 。

**吴涛** [47:04]
经常需要 3 到 4 个字节 。

**Rio** [47:05]
没错 ， 就就越冷僻的那些字节 ， 那个那些字符可能需要的字节数越多 。 但是其实我们现在不是有压缩嘛 ， 对吧 ？

这种东西我觉得问题并不大 。 而且就是那用那个 Gzip 流式压缩的话 ， 你在一台正常的现代的计算机上， 根本感觉不到这种性能的差异 。

所以我觉得还是为了处理方便起见 ， 尽量采用这种方式实现吧 。

**吴涛** [47:31]
没错 。

**Rio** [47:31]
但是我不知道你你不了不了解这个情况 ， 国内很多这种网站还是 。

**吴涛** [47:37]
直到现在都是 GB 呗嘛 ， 对 。

**Rio** [47:40]
呃 ， 好吧 ， 那个我们进到下个环节 。 有什么这个这周有什么小新闻吗 ？ 不不 ， 这周这一个月有什么小新闻吗 ？

### WWDC短评

**吴涛** [47:49]
哈哈哈 ， 真的和 Rio 已经阔别四周了 。

**Rio** [47:53]
两周一期的节目 ， 如果 miss 掉一期就是一个月 。

**吴涛** [47:56]
对 。

**Rio** [47:57]
这再四舍五入一下就是半年 。

**吴涛** [48:00]
没错 。

一期不见如隔半年 。

**Rio** [48:04]
哈哈哈哈 。

**吴涛** [48:07]
OK。其实也没有什么太特别的新闻 ， 然后我最近也比较忙 ， 没有怎么看新闻 。 唯一值得提起的 ， 或者说唯一我知道你肯定会感兴趣的东西 ， 就是呃前两天刚刚结束的 WWDC 了 。

**Rio** [48:24]
还没有结束吧 ？ 现在还在进行中 。

**吴涛** [48:26]
Exactly， 我只是想到如果这一期节目上线的时候 ，也许 。

**Rio** [48:31]
啊 ， 对 ， 那就当我们在录制的时候 ，WDC 其实才开到第三天 。

**吴涛** [48:37]
三天 ， 对 。

**Rio** [48:38]
对 。

**吴涛** [48:39]
一下子暴露了录制的日期 。

**Rio** [48:41]
没关系啊 ， 这个又不是什么行业机密 ，是吧 ？

**吴涛** [48:45]
嗯 。

**Rio** [48:46]
啊 ， 所以其实现在你也你你的表也拿到了 ， 对吧 ？

**吴涛** [48:49]
对 。

**Rio** [48:50]
你买了一款什么表 ？

**吴涛** [48:52]
呃 ， 女朋友给我买的那个 42 毫米的 。 呃 。

**Rio** [48:57]
是 sport 还是钢的 ？

**吴涛** [48:59]
钢的 。

**Rio** [48:59]
对 。 咦 ， 高档 。 然后呢 ， 什么什么带子 ？

**吴涛** [49:02]
就最普通的黑色带 。

**Rio** [49:05]
黑色是那个皮带那一款吗 ？

**吴涛** [49:08]
呃 。

**Rio** [49:08]
啊 ，OK。

**吴涛** [49:08]
这不是皮带吧 ？ 硅胶的应该是 。

**Rio** [49:11]
嗯 ？ 钢的还是默认配硅胶的吗 ？

**吴涛** [49:13]
钢的也是默认配硅胶 ， 就是 。

**Rio** [49:14]
啊 ， 那个不叫硅胶 ， 那个叫想想叫什么来着 ？Fluorastar 吗 ？

**吴涛** [49:19]
啊 。

**Rio** [49:21]
终于想起它叫它终于记得它念什么了 。 啊 ， 你觉得那个手感怎么样 ？ 那个带子 。

**吴涛** [49:29]
就还 OK 吧 。

**Rio** [49:31]
还 OK 啊 。

**吴涛** [49:32]
我我也不知道 ，因为我从来不戴表 ， 你就能就不是 ， 俗话说穷玩车富玩表嘛 ， 那我肯定是不是玩表那一类 ， 所以我也说不上来 。

而且我有一很惨痛的 ，有一件很惨痛的事情 ， 就是我在呃初中的时候 ，有一天看到那个呃地摊上卖的漂亮的塑料电子表 ， 非常高兴 ， 买了一块 。

然后从那那个那个塑料电子表的后盖是镀镍的 ， 然后从那一天开始 ， 我对镍产生了过敏 。 就 。

**Rio** [50:06]
啊 ？ 真的有金属过敏 ？

**吴涛** [50:08]
任何活泼金属戴在我手上都会立刻起包 。

**Rio** [50:14]
所以在 。

**吴涛** [50:14]
就是这什么原理到底 ？ 我就是对金属活泼金属过敏啊 ， 对对贵重金属比较比较比较惰性一点的金属就没问题 ， 什么铝啊 。

**Rio** [50:24]
所以所以你这是暗示我们给你买个金表 ？

**吴涛** [50:27]
对 ， 给我买给我买个金表吧 ，不过还是先 。

**Rio** [50:31]
所以所以你连铝的都不能戴 ？

**吴涛** [50:33]
铝的应该可以 ，因为铝铝会被氧化嘛 ， 对吧 ？

**Rio** [50:39]
你等一下， 你说活泼金属怎么定义一下 ？

**吴涛** [50:41]
活泼金属就是镍啊 ， 啊铬啊 ， 锰啊 ， 主要是镍其实 。 就我相信我之前查过 ，因为德国也有很多人就是过敏 ， 就主要是镍这种东西 。

**Rio** [50:57]
因为我想如果你对铝过敏的话 ， 那你还用得了 iPhone？

**吴涛** [51:00]
不行啊 ， 肯定不行 。

**Rio** [51:02]
就只能装 。

**吴涛** [51:03]
我连铝锅都端不了是吧 ？

**Rio** [51:07]
好吧 ， 所以那个就是体验上我觉得可能 。

**吴涛** [51:11]
不 。

**Rio** [51:11]
你觉得还好吗 ？

**吴涛** [51:12]
我的意思就是我这么大以来 ， 这是第一次正儿八经的每天都戴表 。 当然我之前有一块那个呃德国那个叫什么 Braun， 就是博博朗那个复刻版的最普通的电子表 ， 就是看起来和 iPhone 啊 ，不是不是 ， 看起来和 iPhone 神似 ， 只不过那个是正儿八经的 ， 就是只能显示 6 个数字 ， 这样非常古老的 。

**Rio** [51:36]
呃 ， 所以你你戴了多久了 ？ 哪的 ？

**吴涛** [51:39]
不到 ， 应该一个月吧 ， 差不多 。

**Rio** [51:42]
OK， 所以感觉如何 ？

**吴涛** [51:44]
嗯

，但但就只是一块表而已吧 ， 我觉得 。

**Rio** [51:48]
不不 ， 你就上面那些那些软件啊 ， 那种各种什么 watch extension 啊 ， 这你觉得好用吗 ？

**吴涛** [51:54]
实用性并不太高 ， 必须说对 。

**Rio** [51:57]
对 ， 我也觉得 。 主要的原因就是因为它太慢了 。 我经常一个很久的状况 ， 我我点那个 glass 出来一个 ， 比如说地图吧 ， 上次就我在 idcone 上吐槽最久的 ， 我等 10 秒 ， 我有那个功夫 。

**吴涛** [52:11]
屏幕已经黑了 ， 它还没有 load 出来 ， 对吧 ？

**Rio** [52:13]
对啊 ， 我等那功夫出来 ， 我都直接手机看了 ， 好吧 。

**吴涛** [52:16]
Somehow someway， 我发现这个是就是你用一段时间之后， 它会它就会变快的 。

**Rio** [52:21]
啊 ，是吗 ？

**吴涛** [52:22]
我不知道这是我的错觉还是怎么样 ， 就是一开始的一周我也有这样的状况 ，但是后来就渐渐还好 。

**Rio** [52:28]
好吧 ， 所以我就在今今天我在那个 Twitter 上跟他们讨论嘛 ， 就说就他们在说 ， 这不是刚好 WDC 上说了那个 WatchOS 2， 它会出那个原生的 SDK 嘛 。

**吴涛** [52:41]
对 。

**Rio** [52:41]
可以直接跑在 watch 上面 ，因为之前的话 ， 那个其实所谓的那个 watch app 都只是一个远程桌面 ， 差不多这个意思 。

**吴涛** [52:50]
嗯 。

**Rio** [52:50]
你是显示在手手表上 ，但是那个整个逻辑是跑在手机上面的 ， 通过蓝牙来通讯嘛 。

**吴涛** [52:55]
对 ， 这这是一个这是一个物理世界里的 MVC 分隔 ，MVC 跑在你的裤兜里 ， 然后 V 在你的手腕上 。

**Rio** [53:07]
对 ， 那这个就是一个问题 ， 就是说挺费电 ，而且挺但慢的 ， 我已经讲了 ， 就是一个很大的问题 ， 就是蓝牙通讯的时候 ， 手机的 CPU 和表的 CPU 都不能休眠 ，而且表还表的屏幕还是亮着的嘛 ， 你的手一直看着它 ， 对吧 ？

然后这样其实对两边的电池续航时间都会有影响 。其实反而你是跑在这个表上原生的一个 SDK 的话 ， 反而 。

**吴涛** [53:28]
要好一些 。

**Rio** [53:29]
好也好一些 ，因为它可以快速的完成 ，因为现在 CPU 其实是很快的 。 那个 watch 里面他们说的是应该是就是 A5 的那个架构做小了放进去的 ， 然后那个计算是非常快的 。

**吴涛** [53:41]
哎 ，performance 不是说只有 A4 的级别吗 ？

**Rio** [53:44]
A5 我当时比较清楚记得是 A5。

**吴涛** [53:46]
OK。

**Rio** [53:47]
因为现在 A5 是在苹果大多数的呃卫生级的老旧设备里面大量存在的 ， 比如说那个 iPad 呃 2 还没有在卖的吧 ， 还在卖 。

**吴涛** [53:56]
iPad 2。

**Rio** [53:57]
然后 iPad iPad mini， 然后那个 Apple touch， 就这个就在用 A5， 然后那个还有 Apple TV， 都是 A5 处理器嘛 。

**吴涛** [54:06]
对 ， 反正对啊 ， 用到现在我的感觉就是

， 嗯 ，有一些 APP 我觉得自己可能会用到 ， 比如说德铁的 APP， 就是它会告诉你说下一班火车还有几点来 ， 啊 ， 下一班火车现在在哪 ， 然后你需要去哪个站台 。

**Rio** [54:25]
嗯哼 。

**吴涛** [54:25]
但是从来没有机会用到过 。 然后最实用的功能就是有 ， 或者说最常用的功能就是有邮件来的时候抬手看一下这邮件值不值得看 。

如果值得看的话 ， 就切换到手机或者电脑上去看 。 然后再就是回短信喽 。 就是它我觉得让我最迄今让我最舒服 ， 或者说让我最意外的一点就是它的语音识别准确率非常非常高 。

啊 。

**Rio** [54:56]
对 ， 比比 iPhone 上的还高 ， 很奇怪 。

**吴涛** [54:59]
而且很神奇的是 ， 我的手表的系统语言是英语 ， 手机的系统语言是德语 ， 然后呃我用中文说话 ， 它可以准确的把我说的话识别为中文 ， 即便对方给我发的是英文 。

**Rio** [55:12]
没错没错 ， 我也觉得这个事情超神奇 ， 我不知道他怎么做到的 。

**吴涛** [55:15]
对 ，而且 。

**Rio** [55:15]
但是我现在没法重现那个事情了 ， 我不知道怎么怎么弄 。

**吴涛** [55:20]
什么意思 ？

**Rio** [55:21]
就是我现在又只能输入英文了 ， 就是语音输入 ， 就很奇怪啊 。 我也就之前我刚来的时候 ， 啊是用有一段时间是用 ， 就是你说那种情况 ，因为系统语言是英文嘛 ， 然后回复的时候是出错 ， 它竟然能听出来是中文 ， 然后给我出中文的字 。

但是自从升那个 1.0.1 之后， 好像又不行了 。

**吴涛** [55:40]
哎 ， 这个太奇怪了 ， 我一直都可以 。 而且它很神奇的就是我我说 Audi， 我说奥迪 ， 它会帮我转成 Audi，A-U-D-I， 然后这四个拉丁字母加在中文里面 ， 就我觉得还 。

**Rio** [55:54]
所所以我的猜想是这样子 ， 就是说它为了因为那个手表上的输入比较受限嘛 ， 它肯它苹果肯定在后台上对这个事情做了一个什么特殊的处理 ， 就是 。

**吴涛** [56:04]
后台上放一个人在那听解释吗 ？

**Rio** [56:07]
哈哈哈哈 。

**吴涛** [56:08]
雇了 100 万个印度人， 然后 。

**Rio** [56:11]
这这不是那个什么那个 Silicon Valley 里面那一期黑他们的用的事情吗 ？

**吴涛** [56:16]
没有 。

**Rio** [56:17]
嗯 ， 就我觉得它肯定是用了一个更加费劲的方式去处理这个 Siri 的语音输入 ， 就包括这个多语言识别啊 ， 还有这个准确度上是有很大的提升的嘛 ， 相比于那个 iPhone 上面那个 Siri 来讲哈 。

**吴涛** [56:31]
对 。

**Rio** [56:32]
因为感觉这样成本应该是服务器成本是蛮高的 。 嗯 ， 所以其实你看你用的那几个都是所谓的原生的 APP， 你没有用第就是第三方的 APP， 那个体验都不不太好吧 ？

**吴涛** [56:46]
也还可以吧 ， 我最 。

**Rio** [56:48]
你有你有用哪个第三方的体验比较还是比较流畅的吗 ？

**吴涛** [56:51]
WhatsApp，WhatsApp 还可以 。

**Rio** [56:54]
啊 ， 通讯类的 ， 对 ， 还行 。

**吴涛** [56:56]
然后 Gmail 其实也还可以 ， 就是 Gmail 有 。

**Rio** [57:00]
Gmail 有 watchOS watch 的呃扩展 ？

**吴涛** [57:03]
Gmail 它没有直接 watch 的扩展 ，但是它可以把 message 送到 watch 上 。

**Rio** [57:09]
啊 ， 这个还不错 。

**吴涛** [57:10]
对 ， 然后我还用其他 ， 比如说嗯 ，Instagram 也还 OK 了 ， 然后有一个德国的天气网站也还挺好 。 然后对 ， 反正还比如说那个叫什么 clear， 就是那个 to-do list clear。

**Rio** [57:28]
啊 ，clear。

**吴涛** [57:29]
然后再有 Lufthansa 的汉莎航空的也还 OK。 就做的好的第三方 APP 还是有的 ，但总体来说 ， 嗯 ， 就还就还好吧 。

就这不是一块 ， 这不是一个像 iPad 那样 ， 就是我在拿到 iPad 第二天 ， 我说我靠 ， 我的后半生离不开这个东西了 。Apple watch 没有给我这样的感觉 。

**Rio** [57:53]
嗯 ， 就是一个可有可无的产品吧 ， 这样说准确吗 ？

**吴涛** [57:59]
Nice to have 的产品 ， 对 。

**Rio** [58:01]
嗯 ， 就没有也无所谓 ，有的当然更好了 。

**吴涛** [58:05]
对 。

**Rio** [58:05]
啊 ， 还没有出现所谓的 killer feature 哈 。

**吴涛** [58:08]
对 ，但我觉得 killer feature 早晚会出现 。

**Rio** [58:12]
等它那个原生的 SDK 出来之后， 现在是什么情况 ？ 就是说是可以开发者可以马上已经可以拿到这个 SDK 来测试了吗 ？

还是怎么样 ？

**吴涛** [58:22]
应该是可我昨天下了那个 ， 我昨天重新激活了我的 Apple developer 账户 ， 扔了 100 欧元进去 。 呃 ，因为我之前在公司 ， 就是在我的前公司里面有一个那个 enterprise program， 然后我就把个人的我就把个人的退了 。

**Rio** [58:40]
OK。

**吴涛** [58:41]
然后离职之后， 反正一直也没碰 ， 就一直也没重新开 ， 然后直到昨天再重新续续上之后， 又把那个 S 呃把新的啊 ， 现在有两个版本的 XXX code beta， 一个是 X code 7.0 的 beta， 另一个是 X code 6.4 的 beta。

然后 7.0 的 beta 里面已经包含了 ， 如果没理解错的话 ， 应该已经包含了 watchOS 2.0。 然后对 ， 愿意的话可以去摆弄摆弄试试 ， 我反正今天录完节目之后应该就会摆弄摆弄试试 。

**Rio** [59:15]
所以所以你体验一下到底能做出一个做出什么样一个花来 ， 然后看看有什么提升 ， 体验上的提升了 。

我觉得就如果能原生在表上跑 ， 然后那个响应速度能到原生那些 APP 的层层次的话 ， 我觉得整个体验会好很多 。

但现在确实太糟糕了 。

**吴涛** [59:35]
嗯 ， 我觉就是 somehow someway， 我觉得这个呃 Apple watch 其实可以拿来做很多不需要那个显示屏的事情 ， 就是 。

**Rio** [59:45]
嗯 ， 比如说 ？

**吴涛** [59:47]
用到就是在中国应该是汉朝的时候 ， 就是人们商人们有一种秀礼数 ， 就是他们看了一个商品 ， 然后两个人要交易的时候 ，他们会把那个很长的袖子套在彼此的手上， 然后按对方的手 ， 然后按对方的手就可以知道对方就是要出什么价 。

对 ， 你按对方手指的某一个地部分 ， 对方就明白了你要出多少钱 ， 然后对方可以按回来还价 。 我觉得 Apple watch 可以做类似的事情 ， 就比如说我把手背到后面 ， 然后以某种特定的频率晃这块表 ， 然后这块表就可以在别人的手腕上产生某种特定的信号 。

然后对 ， 这样就可以 。

**Rio** [1:00:32]
不用啊 ， 你现在不是就直接那个在表盘上画那个小花吗 ？

**吴涛** [1:00:36]
对 ，但此时旁边看你表盘的人是看得到的呀 。

**Rio** [1:00:40]
啊 ， 你要有一个秘密的手势 。

**吴涛** [1:00:43]
对 ， 你要有一个别人察觉不到的方式来彼此通讯 。

**Rio** [1:00:48]
所所以一个比较比较宅 ， 比较 geek 的方式是什么 ？ 经常那些你看到那个 ， 比如说这个 ， 就是欧美的那个呃年轻人， 或者说什么兄弟会碰头的时候 ， 会有一堆手特别的手势吗 ？

**吴涛** [1:01:02]
哦 。

**Rio** [1:01:03]
对吧 ？ 我们要带着以后要带着表来玩这件事情吗 ？

**吴涛** [1:01:07]
哈哈哈 。

**Rio** [1:01:08]
把那个整个要记录下来 ， 要计算一下你这个是否某一个动作做标准了 ，不标准不给开锁 。

**吴涛** [1:01:14]
或者或者最简单的就是直接做一个那个莫尔斯莫尔斯表莫尔斯码的 ， 然后 。

**Rio** [1:01:23]
按表盘 。

**吴涛** [1:01:23]
对 ， 你敲表盘 ， 然后对方就会收到那个你敲的震动 。

**Rio** [1:01:27]
然后通过那个什么 taptic engine 直接在那里显示 ， 直接打到手上是吧 ？

**吴涛** [1:01:32]
对 。

**Rio** [1:01:32]
然后通过人工的方式去读那个 code。

**吴涛** [1:01:35]
对 ， 然后你逼 ， 然后提供一个菜鸟模式 ， 就是对方发呃莫尔斯码 ， 然后你看表盘 ， 这个表盘会把莫尔对方的莫尔斯码翻译出来 。

**Rio** [1:01:46]
要不要不你这个第一个 watch app 就做这个吧 ， 我觉得挺有市场的 。

**吴涛** [1:01:49]
可以可以 ， 可以试试做一下 。

**Rio** [1:01:51]
感感觉实现起来也比较简单了 。

**吴涛** [1:01:53]
对 。 哎呀 ， 对 ， 我前两天看那个 。

**Rio** [1:01:58]
这这段我们要咖掉吗 ？ 因为这个属于那个什么 business product idea 这个 。

**吴涛** [1:02:03]
嗯 ， 我我始终觉得 idea is cheap, show me the code。 所以各位听众里面如果有哪个人做出来一个 ， 欢迎你们来开源 ， 然后大家可以呃大家可以下来下下来编一下 。

**Rio** [1:02:16]
就有一个 。

**吴涛** [1:02:17]
有一个新闻就是 ，有一个新闻就是现在好像 Apple 可以不用注册 developer， 就可以把程序跑在实体机器上了 。

**Rio** [1:02:26]
嗯 ？

**吴涛** [1:02:27]
对 ， 就是如果各位听众不知道的话 ， 就是在以前你要为你要为 iOS 开发程序 ， 呃理论上是不需要交钱的 ， 你只需要下载 X code， 然后写一程序 ， 然后在模拟器里面跑 。

但是如果你想要把这个 APP 在你的实体机器上跑的话 ， 你必须先去注册 。 但是目前看来 ， 就是如果我理解的这个新闻没错的话 ， 将来你不需要呃一个开发者账号 ，也可以把你的 APP 直接跑在你的实体实体设备上 。

**Rio** [1:02:56]
但只能是跑你自己那台机器 。

**吴涛** [1:02:58]
应该是只能跑你自己那台机器 。

**Rio** [1:02:59]
那也完全够了 ， 自己玩票用 。

**吴涛** [1:03:01]
对 ， 这就是 。

**Rio** [1:03:02]
自己写给自己 。

**吴涛** [1:03:04]
那种早期的 homebrew 的方式又可以流行起来了 ， 就是你把原档案发到 GitHub 上， 然后别人当下来 ， 然后靠呃编译一下就可以跑在自己的机器上了 。

**Rio** [1:03:13]
对 ， 这可能是很多这种就是玩票 ，他也不打算真的去放一个东西上架到 App Store 里面那种票友吧 。

**吴涛** [1:03:21]
嗯 ， 没错 。

**Rio** [1:03:21]
编程票友的抱怨 ， 就是我干嘛要每要花个每年 100 刀去买这个我一年用两次的东西 ， 对吧 ？

**吴涛** [1:03:28]
对 。

**Rio** [1:03:29]
呃这安卓就没有这个问题 ， 插上线什么都可以装了 。 啊 ， 对 ，有这个我觉得还是挺好的 ， 起码我我会有更多东西说 ， 哎 ， 那我也也学一下这个 Swift 来写一个东西来玩一下 。

**吴涛** [1:03:42]
对 。

**Rio** [1:03:44]
但是起码到目前为止 ， 我们对这个对这个表的这个物理的就是 spec 叫什么来着 ， 硬件参数是还不太清楚的是吧 ？

**吴涛** [1:03:53]
嗯 ， 好 ， 对吧 ？ 那个 cheapvac 好像还没有把它 cheap work 还没有把它拆开 ， 然后 。

**Rio** [1:04:01]
Cheapvac。

**吴涛** [1:04:02]
哈哈哈 ，sorry， 德语德语翻译又出来了 。 嗯 ， 把它放在 X 光机下面照一下， 然后告诉我们上面都是什么 。

**Rio** [1:04:13]
嗯哼 ， 然后包括内存 ， 它内存是确定的是 512 兆 。

**吴涛** [1:04:17]
512 兆应该是 。

**Rio** [1:04:19]
但是多少能给应用用 ， 多少是被那个系统占掉了 ， 现在也不知道 。

**吴涛** [1:04:23]
对 。

**Rio** [1:04:23]
然后刚才我们讨论到的是 A4 的芯片呢 ， 还是 A5 的芯片 ， 然后它做那么小到底是有多 ， 就是功耗上会有多大限制 ， 这也都不太清楚嘛 。

**吴涛** [1:04:32]
嗯 。

**Rio** [1:04:33]
所以这就靠你去研究一下这个啊 ， 呃 X code 7.0 的版本之后能不能做出一个好玩的东西来 。

**吴涛** [1:04:42]
好 。

**Rio** [1:04:42]
快把那个莫尔斯码做出来 ， 我们先先给我装上， 我们先试试 。

**吴涛** [1:04:48]
Release date。

**Rio** [1:04:49]
我等等 ， 我我还得先得学莫尔斯 code， 这怎么办 ？

**吴涛** [1:04:52]
啊 ， 这个学起来挺快的 。

**Rio** [1:04:54]
是吧 ？

**吴涛** [1:04:55]
至少你至少你是会两个的 ，S 和 O 嘛 。SOS 就是三呃三短 ， 然后三长 ， 再三短 ， 三短三长三短 。

**Rio** [1:05:06]
为什么不是三长两短呢 ？

**吴涛** [1:05:09]
因为 S 是三长啊 ，S 是三短 ，O 是三长 。

**Rio** [1:05:13]
嗯 ， 好吧 。

**吴涛** [1:05:14]
对 。

**Rio** [1:05:15]
所以现在其实我们对这个 watch 呃原生的 watchOS 2 的 SDK 还没有太多可以讲的哈 ，因为现在只是公布出来 ， 还没有真的去试过 。

那可能以后等我们的吴涛同志去试了之后， 我们在今后的节目里面再来提一下 。 这次 WWDC 上还发布了一个我觉得挺开心的消息 ， 就是 Swift 2。

**吴涛** [1:05:37]
对 。

**Rio** [1:05:37]
并且它开源了 。

**吴涛** [1:05:38]
它开源了 ， 对 。 这个是当时我也是在看电视的时候 ， 呃对 ， 我和我女朋友一般在做饭 ， 然后一边在看 WWDC， 然后我看到那个说 。

**Rio** [1:05:48]
多么温馨的一个场面 。

**吴涛** [1:05:49]
对 ， 忽然双手举高说 Swift 2 开源喽 ， 然后女朋友疑惑的问那是什么意思呢 ？ 哈哈哈 ， 然后又进入了教学模式 。

**Rio** [1:06:01]
多多多么幸福的一个场景啊 。

**吴涛** [1:06:03]
Yeah。

**Rio** [1:06:04]
你看在在听的单身狗们感受到深深的恶意没 ？

**吴涛** [1:06:09]
我我没有这个意思 。

**Rio** [1:06:13]
哈哈哈 。 嗯 ，但它开源是说发布了这个啊 iOS OS X 和 Linux 的版本 。

**吴涛** [1:06:22]
对 ， 我觉得这还挺 ， 当时我听到 Linux 也是心里一惊 ， 心想说我靠 ， 这是多久没有在 Lin 呃在 WWDC 上听到 Linux 的名字了 。

而且不敢相信的是 ， 好其后稍后又听到了一次安卓的 ，而且是一种以一种正面的方式听到安卓 。

**Rio** [1:06:45]
对啊 。

**吴涛** [1:06:46]
就是它在宣布那个 Apple Music 将会在安卓的上推出的时候 ， 我心里还觉得嗯 ， 这是发生了什么 。

**Rio** [1:06:55]
而且我跟你说那个他们还出了一个安卓的 APP，不是音乐那个 ， 叫做叫做什么安卓 migration 吧 ， 可以可以从安卓上就帮助你从安卓手机切换到 iPhone 了 ， 简单来讲 。

**吴涛** [1:07:08]
啊 ，OK。

**Rio** [1:07:10]
因为安卓是可以拿到很多系统的资料的嘛 。

**吴涛** [1:07:12]
对 。

**Rio** [1:07:12]
然后他给你做了这么一个一键导入 ， 切换到那个 Apple ID 里面 ， 然后再给你就是直接可以帮你设置好很多东西了 。

这这个还是蛮狠的 。

**吴涛** [1:07:21]
Mac 上面也有 ，也曾经有过这个什么 。

**Rio** [1:07:25]
没错 ， 可以从 Windows migrate 过来 ， 它它它就把等于就是这个就是 iOS 版的那个东西了 。

**吴涛** [1:07:31]
OK。

**Rio** [1:07:32]
叫做叫做 migrate migration assistant 吧 ， 应该是 。

**吴涛** [1:07:35]
OK。

**Rio** [1:07:36]
我等下我确认一下是不是叫这个来着 。 对 ，migration assistant。

**吴涛** [1:07:39]
嗯 。

**Rio** [1:07:40]
就是这点还是蛮狠的 ，因为你知道这个东西是是单向街嘛 ，one way street。

**吴涛** [1:07:44]
对 ， 那肯定能 。

**Rio** [1:07:46]
因为因为 iOS 里面没有 ， 就除了苹果之外没有 ， 就哪怕苹果吧 ， 应该是不太可能拿得到那些应用里面的资料 ， 就是有这个沙盒模型的限制 ，而且它把系统权限锁得很死嘛 ， 你不可能做 ， 就第三方是没有办法做这么一个应用 ， 装到一个 iOS 里面 ， 然后再把数据导到那个另外的地方去 。

当然可能拿那个通讯录啊 ， 这种比较常有照片啊 ， 这种常见的还可以 ，但其他的就不行了 。 我不太清楚那个安卓 migration 这个 APP 到底能做多少的事 。

**吴涛** [1:08:16]
嗯 ， 总之苹果的反正这一套东西就是一堆一堆生满稻次的丛林 ， 你进去就出不来 。

**Rio** [1:08:23]
没错 。 那再说回那个 Swift 开源的事情啊 。

**吴涛** [1:08:26]
嗯 。

**Rio** [1:08:26]
就你觉得他们为什么会选会会做这件事情 ？ 他们的动机是什么 ？

**吴涛** [1:08:32]
呃 ， 我觉得他们还是想要把 Swift 这个目前看起来非常优秀的语言特性尽可能的拓展开来 ， 然后借此来呃一方面是能让语言本身能够新晋火船下去 ， 另外一方面也是希望能够借此让其他平台上的人尝一尝呃给苹果编程是一种什么样的体验 。

**Rio** [1:09:03]
哈哈哈 ， 没错 。

**吴涛** [1:09:05]
因为你以前在 ， 除非你是一个非常非常非常非常有狩猎倾向的人， 你是一般不会在其他操作系统上试图去搞呃 Objective C 这套东西的 。

就是你去你可以去采用那个玩意叫什么 open step 呃这套东西来呃在其他平台上编译 Objective C 是可行的 ，但是从来没有人这样做 ， 或者说你这样做的人最后都把头发抓光然后出家了 。

嗯 。

**Rio** [1:09:34]
哈哈哈 。

**吴涛** [1:09:34]
而 Swift 2 如果开源并且跨平台的话 ， 那你也许将来可以在不知不觉的在呃 Linux 上面爱上这门语言 ， 然后你发现你的这个知识可以迁移到给苹果开发系统 ， 呃给苹果开发软件 ， 那也许你就会随手去做一个呢 ，也许这也是苹果的考量之一 。

**Rio** [1:09:57]
我觉得可能最眼下最务实的一个事情就是说很多这个 iOS 开发者 ，他因为你知道 iOS 的现在现在不是有个风潮吗 ？

就是说我们做一个新的产品或者服务的时候 ， 连网站那个都省了 ， 直接就做一个 API 的后台 ， 再加一个 iOS 客户端就搞定了 ， 对吧 ？

**吴涛** [1:10:14]
嗯哼 。

**Rio** [1:10:15]
但是呢 ， 这个服务端那边一般不可能用 ， 刚才讲了不可能用苹果的东西来写之前就 。

**吴涛** [1:10:22]
对 。

**Rio** [1:10:22]
非常少 。

**吴涛** [1:10:23]
用 Objective C 用 Objective C 写后台已经是 20 年前的事情了 ，并且 。

**Rio** [1:10:30]
哈哈哈 ， 对 ， 就连应该我记得是连苹果自己那个叫什么 Web 什么来着 ？

**吴涛** [1:10:35]
Web 呃 Weblogic？Web。

**Rio** [1:10:38]
不是有它有一个叫什么 ？

**吴涛** [1:10:41]
我来搜一下 。

**Rio** [1:10:43]
WebObjects。

**吴涛** [1:10:44]
对对对 ，WebObject。WebObject 后来转成 。

**Rio** [1:10:49]
Java 了 。

**吴涛** [1:10:49]
后来转 Java 吗 ？

**Rio** [1:10:51]
没错 。

**吴涛** [1:10:51]
OK。

**Rio** [1:10:52]
这个我很确定 ， 就是苹果曾经它是自己是有一套这个 ， 当然是那个是 Web 1.0 时代哈 。

**吴涛** [1:10:58]
对 ， 非常非常古老的时代 。

**Rio** [1:11:00]
因为最初发布的时候是 19 年前 ，96 年的时候 ， 然后它最开始的时候是那个 Objective C 写的 ， 后来是都因为面对现实改成了 Java 来实现的 。

啊 ， 这这这还是蛮坑爹的嘛 ， 你要学两个语言 ， 两种 run time， 然后各种不一样的区别 ，API 都完全不一样 。

然后有了这个 Swift 2， 就 Swift 它如果开源有这么新的时候 ， 你可以做到这么一件事 ， 就是前那个客户端的开发者和服务端 API 的开发者可以是同一班人嘛 ， 或者说就不用再学两套语言了 ， 就整个都是一样的 。

唯一现在可能比较存疑的哈 ， 就是这个标准库和第三方库的问题 ，因为刚出来肯定是没有的 ，因为它那些比较好的现成的这个 ， 就是因为为什么说这个 Objective C 做那个客户端开发比较好用 ， 或者说 Swift 做客户端开发开发比较好用 ，是因为它有那个 Coco 嘛 ，也是叫 Coco 嘛 ，UI kit 这一套东西 。

**吴涛** [1:12:00]
Coco 也对啊 ，因为在 Mac 上面 。

**Rio** [1:12:03]
啊 ， 对 ， 就 Mac 和 iOS 上面都是同一套 ， 一个是经典版 ， 差不多这么理解吧 。

**吴涛** [1:12:08]
嗯 。

**Rio** [1:12:09]
嗯 ，但是它现在如果开源到 Linux 上面去的话 ，其实我不清楚它只有语言还有编译器开源呢 ， 还是说它会把这一套比较完善的这个标准库也拿过去用 ， 我觉得可能不太现实 。

**吴涛** [1:12:23]
对 ， 应该是 。

**Rio** [1:12:23]
应该太多了 。

**吴涛** [1:12:24]
我希望我我我觉得苹果的希望应该是能够让第三方开发者自己生长出一套 Web。

**Rio** [1:12:33]
就开发社区来做这个事嘛 。

**吴涛** [1:12:35]
对 。 Swift on rails。

**Rio** [1:12:37]
哈哈哈 。

**吴涛** [1:12:40]
Swift on power cables。 就是一群燕子站在这个电线上面 。

**Rio** [1:12:46]
哈哈哈 ，OK， 这个我们的这个连项目名字都想好了 ， 开始干吧 。

**吴涛** [1:12:50]
对 。

**Rio** [1:12:52]
嗯 ， 就所以这这个我觉得好处还是很显而易见的哈 ， 就是可以看实现 ， 刚才我说的那一点 。 然后其实从一个就是这个 mind share 这个脑脑力的争夺战来讲 ，其实我觉得现在定位最好的应该是 Android 吧 ，因为 Java 很多人都会嘛 ，Java 可以写这个客户端 ， 可以写嵌入式 ， 可以写服务端 ， 可以写桌面桌面应用 ， 当然桌面应用不太适合 ，但是总体来说还是一个通适用

性非常广的语言嘛 。

**吴涛** [1:13:24]
但有意思的是 ，Google 正在有意无意的把 Java ditching 掉 ， 你不觉得吗 ？ 就是首先 server side 肯定要用 go language 写 。

**Rio** [1:13:33]
这件事情已经成立了吗 ？ 我觉得还没有吧 。

**吴涛** [1:13:36]
它正在试图朝这个方向前进不是吗 ？ 你不觉得 ？

**Rio** [1:13:39]
呃 ， 这点事情我是觉得是存疑的 ， 就是 。

**吴涛** [1:13:43]
你觉得 Google 在我们有生之年不会抛弃 Java 吗 ？

**Rio** [1:13:47]
起码在安卓的这一端我觉得是可能比较难 ，因为因为其实你真的用 go lang 写客户端的话 ，其实发现还是蛮坑蛮多的 。go go lang 写 。

**吴涛** [1:13:56]
可是我们上次不是提到了它的那个叫什么 Sky？

**Rio** [1:14:00]
对 ， 它有这个尝试嘛 ，但是我不太清楚这件事情是否真的能够做得成 ，因为这个惯性还是蛮大的 。

你不知道 ，因为这个 Java 是什么 ？ 教学级语言啊 。

**吴涛** [1:14:12]
啊 ， 我以为你要说小强级语言 。

**Rio** [1:14:15]
哈哈哈 ，有一个意思吧 ， 就是在学校里面它的培培养的人啊 ， 就是教学的时候就使用这个东西 。 我觉得这个对一大批的这个程序员的成长的经验上还是非常重要的影响的 。

所以我不太确定它这个能够短期内实现这一点 。 而且

哪怕是在服务端 ， 它在用 go 去替代 Java，也是在比较小范围的有限度的去进行一个尝试 ，而并不是说全就全公司的这么去推这么一个东西 。

**吴涛** [1:14:42]
如果纯粹以前后端使用单一语言来衡量的话 ，不考虑市场份额 ， 那 Windows Phone 难道不是最好的吗 ？ 就你在 Windows。

**Rio** [1:14:50]
对 ， 所以其实我们来现在看 ， 现在微软其实挺有意思的一个情况 ， 就是它那个 C# 其实是做得挺好的 。

**吴涛** [1:14:57]
对啊 ， 通吃所有平台所有端 。

**Rio** [1:15:00]
对 ，而且如果我理解没错的话 ， 它有那个 CLR 的 run time 之后， 它编译那个生成那个 C， 就是你甚至不一定要用 C# 来写 Windows Phone 的应用吧 ？

**吴涛** [1:15:10]
对 。

**Rio** [1:15:10]
可以用那么 F# 来写也可以 ， 对吧 ？

**吴涛** [1:15:14]
对 ， 或者什么 Objective Objective C.NET。

**Rio** [1:15:18]
对 ， 这这之类的东西 ， 就其实它的那个定位是更好 ， 当然它因为没有没有什么 ， 没有市场占有量 ， 这件事情就对大维数来说没有什么意义 ， 就我们只讨论安卓和 iOS 两种两个情况来看 ， 就是苹果在这上面算是我觉得稍微是有点吃亏的 。

**吴涛** [1:15:37]
嗯 ， 很难说吧 ， 我觉得就 。

**Rio** [1:15:40]
嗯哼 。

**吴涛** [1:15:41]
嗯 ， 我觉得

苹果是试图以语言本身的优势 ，以及它在客户端的比较相对来说比较广泛的开发者群去反攻服务端 ， 去反反过来去试图向服务端扩展这一技术 。

而我看不到 Google 有一种新的语言可以担此重任 。 另一方面 ，Google 好像本身也没有这个心思 。

**Rio** [1:16:17]
它之前不是大家都在猜它会不会用那个叫那个叫什么来着 ？ 之前宣布有没有搭载的 。

**吴涛** [1:16:24]
Dart。

**Rio** [1:16:25]
对 ，Dart， 对 ，Dart 不就是 Sky 嘛 。 呃 ，但是我觉得那个事情可能它想的可能还不太一样 ， 那个 Dart 是初衷是要从 Web 那端开始简化这个 UI， 就是就是 UI 的那个构建的方法了 。

**吴涛** [1:16:40]
嗯 。

**Rio** [1:16:42]
但是到了这个安卓上， 我不知道性能啊 ， 还有这些方面真的是靠谱吗 ？ 反正它起码现在没有做这件事了 ， 可能还是有一定的技术门槛的 ， 我觉得 。

**吴涛** [1:16:51]
嗯 ， 拭目以待吧 ， 反正 Google 东西都是要等。

**Rio** [1:16:56]
然后随时可能不就就就 cancel 了 。

**吴涛** [1:16:59]
对 ， 我觉得这次 WWDC 给我的一个印象就是你在那边看着他说 ， 哎 ， 这个东西我们是什么什么样的 ， 然后一转脸你就可以下载下来用了 。

**Rio** [1:17:09]
那还是 deliver 的到了 ，不像 Google 老是画饼 。

**吴涛** [1:17:14]
对 ， 说对 ， 说这个东西我们有了 ， 然后对 ， 各位再等两年就可以用到 。 哦 ， 对 ， 还有一个呃比较小的重点 ， 就是 Swift 2 里面有这个 try catch， 当然他们的语它的语法是 do catch，do 里面就是有个 do block，do block 里面有一些关键的部分 ， 可能可能会抛出异常的部分 ， 你要用 try 呃 try 关键词去 。

**Rio** [1:17:40]
就是有那个 exception 机制了嘛 。

**吴涛** [1:17:42]
对 ， 然后我之前在知乎上写过一篇答案比较啊 ， 比较笃定的阐述了为什么没有 exception 机制比较好 ， 然后现在 exception 机制出来了 。

**Rio** [1:17:58]
被打脸了是吧 ？

**吴涛** [1:18:00]
对 ， 嗯 ，anyway， 我当然我那篇文章里面非常圆滑的没有把话说死 ， 然后我也默默的去改了那个当时的措辞 ， 就说啊 ， 现在已经有了 ， 所以 anyway。OK， 那我们接下来可以进入本期的正题 ，在一小时一个多小时之后开始进入正题 。

### 软件测试

**Rio** [1:18:23]
哎 ， 太好了 ， 我们就能谈半个小时 。

**吴涛** [1:18:25]
对 。

**Rio** [1:18:25]
耶 ， 所以本期的主题是测试 。

**吴涛** [1:18:29]
Testing testing testing testing。 对 。

**Rio** [1:18:32]
然后什么是测试 ？ 解释一下 。

**吴涛** [1:18:35]
呃 ， 好问题 ， 你说什么是测试 ？ 就我其实今天在准备 ， 或者说这段时间在准备这个提纲的时候 ， 想了很多测试的例子 ，但是呃我觉得可以这么说吧 ， 就是测试有两个含义 ， 一个是广义的测试 ， 一个是狭义的测试 ， 就像相对论一样 。

呃 ， 广义的测试可以指比如说 penetration test 也是一种测试 ， 就是看贵公司的网站是否安全 。 我作为一个不管是黑帽子还是白帽子 ，是不是去扫一扫端口呀 ， 破一破密码呀 ， 找一找注入点呀 ， 这些可以叫做测试 ， 甚至嗯哼 ， 英文名字也叫 penetration test， 甚至有一个专门的缩写叫做 pen pen test。

对 ， 然后嗯 ， 发烟测试也可以叫做测试 ， 就比如说发烟 smoke testing。

**Rio** [1:19:30]
对 ， 这我还不太理解 ， 这里面这种各种术语 ， 这个是讲什么 ？

**吴涛** [1:19:34]
Smoke test，smoke testing 实际上大家每天都在做 ， 或者说经常会做 。 呃 ， 比如说你装好了 run rails， 然后你呃开始运行服务器 ， 打开浏览器 ， 输入 localhost:8080， 回车 ， 哎 ， 屏幕上出现了这个 it works 之类的这么一个一个表示 ， 说啊 ， 这个东西开始运行了 ， 这么一个提示 。

**Rio** [1:19:59]
对 。

**吴涛** [1:19:59]
这就这个过程就是一个 smoke test。

**Rio** [1:20:02]
这个 smoke 是何怎么一个说法 ？

**吴涛** [1:20:05]
呃 ， 它应该是借于借用自另外一个领域 ， 我忘了是哪个领域 ，是矿工还是什么啊 ， 工种的一个既有的测试 ， 就是如果你看到冒烟了 ， 说明这个东西是已经开始正常 ， 好像是孤独之类的一个非常古老的术语 ， 发烟测试 。

呃 。

**Rio** [1:20:28]
确定不是摩托车之类的吗 ？

**吴涛** [1:20:31]
应该不是摩托车吧 ， 摩托车冒烟那肯定是有故障 。

**Rio** [1:20:34]
哈哈哈 ， 好吧 。

**吴涛** [1:20:36]
发烟测试指的就是你在呃你在试一个东西 ， 你想要看一看它的那些最为 critical， 最为基本的功能是不是运行 ， 比如说你你想知道啊 ， 你你想知道来电了没有 ， 或者说你想知道是不是停电了 ， 你去搬一个电灯的开关 ， 哎 ， 这就是一种 smoke testing，因为它所测试的并不是你家整个电路是不是完好无缺 ，是不是有地方有破损 ，是不是有地方电阻太高 ，是不是有可能

有火灾的风险 ， 它唯一测试的就是你家的电路是不是在运行 。 但是呢 ， 狭义的测试则是不包括刚才说的 ， 比如说 penetration testing 或者 smoke testing。

呃 ， 狭义的测试其实如果要用比较简单的语言来说 ， 就是

让你知道 ， 让你有一种可以重复的方法来知道自己写的软件是按照你所希望的那些方式而运行的一系列东西 ， 就可以叫做测试 。

**Rio** [1:21:42]
刚才讲了各种各样的测试哈 ， 测试的主要一个目的是什么 ？ 主要的目的是什么 ？

**吴涛** [1:21:48]
基本上就是要有一些呃 ， 基本上测试的意义就是让你有一个可以度 ，有一个可以度量的准则 ， 就是你你因为我们知道你写了一个程序之后， 你会说啊 ， 这个程序看起来是正确的 ， 或者说它在大部分情况下也都是正确的 ，但是你怎么样才能有一种比较可以验证的 、 客观的 、 可以量化的指标来告诉你说 ， 对 ， 这个软件的确是可以工作的呢 ？

这就是测试了 ， 就是你为了获得一些特定的指标 ，而对你写好的软件采取的一系列度量的方法 ， 就是测试 。

**Rio** [1:22:26]
所以就是其实它是一个质量的 ， 就 code 的概念 。

**吴涛** [1:22:31]
呃 ， 对 ， 早期的

早期的测试呃 ，是为了验证程序的 behavior 是不是正确 ，而后期比如说现今的测试很大程度上已经变成了一种呃质检的关卡 ， 就是我们知道有一个

呃验证体系应该是 ISO 9000 吧 ，在软件界好像还有一个另外的编号 92 多少 ， 然后这个认证体系很大的一个指标 ， 就是要看你这个软件公司的测试有没有写 ， 如果有的话是什么样的在写 ， 然后有没有一个专门的负责把关的部门来去叮嘱 ， 去盯着这些测试 。

**Rio** [1:23:19]
嗯哼 。

**吴涛** [1:23:20]
诸如此类 。 对 ， 如今测试已经成了一个特别重要的一个软件工程里面的环节 ， 然后测试又可以分为呃功能性的测试以及非功能性的测试 ，也就是说狭义上的测试又可以分为功能性的测试和非功能性的非功能性的测试 。

啊 ， 功能性的测试也就是说 ， 比如说你要你写了一个函数 ， 这个函数可以返回两个数值的和 ， 然后你写所谓功能性的测试就是你输入 3 和 4， 然后看这个函数是不是返回 7。

**Rio** [1:23:50]
对 。

**吴涛** [1:23:51]
又比如说你你写了一个啊除法的函数 ， 然后你输入 1 和 0， 想要看这个函数会不会返回说除 0 错 ， 这是一种功能性的测试 。

而非功能性的测试则是比如说看你这个函数的执行的速度怎么样 ， 比如说你写了一个加法的函数是正确的没错 ，但是它需要一天才能得出结果 ， 那这样的函数可能没有办法通过所谓的功能性的测试来验证它 。

对 ， 功能性的测试会告诉你说它没问题 ，但是一一旦你去做一个呃 performance testing， 那你会立刻意识到这样的函数是完全不过关的 。

又比如说 。

**Rio** [1:24:32]
这个 performance testing 其实有一个专门的术语 ， 我们叫做 benchmark， 对吧 ？

**吴涛** [1:24:37]
可以这么说 ， 对 。

**Rio** [1:24:38]
嗯哼 。 然后其实就是就就这么说 ， 就是这么算 ，其实 benchmark 是测试的一个子集 。

**吴涛** [1:24:46]
嗯 ， 怎么说呢 ，performance testing 可以归类为 profiling 的一种 ，而 benchmark 则是 profiling 的一个指标 ， 所以我倾向于认为两者还是有多少有点不一样的 。

**Rio** [1:25:05]
OK。

**吴涛** [1:25:07]
因为嗯

， 当然也是可以用 benchmark 最终的分数来作为呃 performance testing 的一个指标也没错 。anyway， 这不重要 ，因为我们本次节目所要集中的这个呃话题 ，其实是在狭义的非呃功能性测试上面 ，而不是非功能性测试 ，因为非功能性测试可以可能涉及到的面实在是太广太广了 。

呃 ， 对 ，因为软件工程本身就是一个非常非常广的话题集 ，而测试又是软件工程上面相当大的一个分支 ， 我们显然不可能在一个预计时间只有两个小时左右的节目里面把呃面目呃面面俱到的吧 ， 测试的每个方面都谈到 ， 所以我们这次主要的集中的呃主题还是在功能性测试上面 ，而且功能性测试里面我们应该只会谈及呃 unit test，也就是单元测试 ， 呃以及部分的所

谓呃 acceptance test，也就是接受性测试 。 我不知道是是交接测试还是中文术语是什么 ， 忘记了 。

**Rio** [1:26:26]
没关系 。

**吴涛** [1:26:26]
Anyway， 对 ， 嗯 ， 所以 Rio 你写测试吗 ？

**Rio** [1:26:32]
嗯 ， 很惭愧 ， 我不写 。

**吴涛** [1:26:35]
伟大的程序员都是不写测试的 ， 这句话我们先 。

**Rio** [1:26:38]
不是 ， 我我一直就在想了解这么一个事哈 ， 就是说我们经常有这个 ，也有一种开发程序的思路 ， 叫做 test driven development 嘛 ，TDD 嘛 ， 对吧 ？

**吴涛** [1:26:48]
对 。

**Rio** [1:26:49]
我一直很好奇这事靠谱吗 ？ 就这么说吧 ， 如果我们把软件工程真的作为一项工程来讲 ， 我们会这么去想它 ， 就是你修一栋楼 ， 你会说 ， 哎 ， 这个楼我们算出来它的承重是比如说 1,000 吨 ， 某一层 ， 对吧 ？

我不知道这个数字是不是靠谱 ， 反正就举随便举一个 1,000 吨 ， 然后我们会从力学结构上计算出它没错 ， 它确实可以这个承受 1,000 吨 ， 就是从计算物理算术这个怎么就是公式算出来就这么多 ，但我们不会真的弄一个 1,000 吨上去给它实际压一下， 对吧 ？

**吴涛** [1:27:24]
嗯

，是这样说没错 ，但我又不打算反驳你 ， 你你还你还有别的要说的吗 ？

**Rio** [1:27:31]
没有 ， 我只是就就在这个思路说下去 ， 就是说其实有很多事情我们是没有办法去真的真的去实践那个条件去测的 ， 就是有些所谓的 edge cases， 对吧 ？

但是软件不一样 ，因为软件很适合模拟各种情况出来 ， 你都可以就是说你 1,000 多场努力输个多加个 0，1 万吨我都可以给你测出来 ， 没有问题 。

但我觉得这个我一直很好奇 ， 这样会不会让人变得奇怪 ， 变得或者变得懒 ，因为我一直觉得要保证软件质量 ， 测试当然是少不了的一个环节 ，但是这个不是最根本的问题 ， 最根本的问题是你要在设计的时候就要想好这个在理论上可不可能会出现这种问题 ， 就或者说这么说吧 ， 你写了一个函数 ， 它有多少种可能的进入方法 ，有多少种可能的

退出方法 ， 中间有多少种可能的这个出现异常的这个原因 ， 我们把这些都每一个都考虑过了 ， 然后再去写函数 ， 就才可以说它是一个啊无错的 ， 一定是按就是就是证明过确实被证明过 ， 确实没有你所有的的路径你都考虑了 ， 没有一个漏掉的东西 ， 这个时候你不用写测试了 ，因为你的在设计的阶段你已经把所有的可能性都考虑过了 。

但是呢 ， 做这件事情本身可能是比较难的 ， 就是说特别是软件工程大了之后， 你可能不可能面面俱到 ， 对吧 ？

所以我们才要测试一些选择一些点 ， 就是说甚至要做统计抽样的办法嘛 ， 我们假设如果这些点过了之后， 我们有较大的信心认为这个东西是设计上是没有问题的 ，但是这个和我刚才讲的那种修楼 ， 修楼你用力学公式那部分怎么怎么结构力学算出来之后， 它肯定能承受这么多 ， 然后我们并不需要真的去加上那个极限的重量去测它能不能实

际承受那么多 ，是是一个概念 ， 就是说我们能够算出来之后， 我们不需要真的去做那些测试了 。 所以我一直很好奇 ， 我们是不是把测试的功能想得太伟大了 ， 或者说测试的重点太多 ，而把这个从这个设计 ， 从这个原理层面的东西放得短一点太少 。

**吴涛** [1:29:40]
OK。 嗯 ， 呃 ， 槽点太多 ，不知道从哪突起 。

**Rio** [1:29:45]
哈哈哈 ， 没事 ， 慢慢来 。

**吴涛** [1:29:48]
开玩笑 ， 开玩笑 。

**Rio** [1:29:48]
我这个就是 。

**吴涛** [1:29:49]
不 ， 我其实其实我还是很比较认同你的看法 ， 说实话 ，因为嗯哼 ， 呃

， 这么说吧 ， 我其实对于测试一直是抱有多多少少有点抵触情绪 ， 嗯 ， 甚至我自己也不是一个非常喜欢写测试的人 ，但是我必须反驳你的一点就是 ， 你觉得测试似乎在软件工程里面被高估了 ，而我则觉得从目前大部分软件的水平来看 ， 它应该是被低估的 。

**Rio** [1:30:22]
哈 。

**吴涛** [1:30:23]
嗯 ， 拿回你这个钢结构的例子 ， 就是你的建筑的例子 ， 就是你会说你设计这一层 ， 它的呃应力可能是呃 2,000 吨或者是多重 ，但是你之所以能得出这个数值本身 ，其实就是因为用来搭这个建筑的钢材真的经历过在一个比较小的规模上的应力测试 ， 啊 ， 你才可以拿到这个钢材相关的数据 ， 然后你才能算出这个钢材在什么样的高度 、 什么样的长

度 、 什么样的直径上面能够承受多大的重力 。 就是呃在现实生活里面 ，在实体世界里面 ，有很多东西的数值真的不是可以算出来的 ， 就比如说化学或者是当然这个是扯远了 ，但就很大一部分程度上， 我们对于很多材料的认知都是非常愚蠢的去拿在实验室里面不停的去试试出来的 。

**Rio** [1:31:30]
OK。

**吴涛** [1:31:32]
包括合金或者是哎 ， 算了 ，不说这些了 ，但总之最重要的一点就是在现实生活里面 ， 测试本身就已经是一个比较 fundamental 的东西 ， 它如此的丝毫见惯 ，以至于你有可能不去不会去重视它 ，因为呃如果你是一个建筑工人的话 ， 或者如果你是一个呃材料力学专家的话 ， 你可能会觉得我在那个软件里面拖一拖线图 ， 然后它自动不就会帮我估估算出来这个东西大概有大

概有什么样的能够承受多大的重量吗 ？ 但实际上这个数值本身就是首先通过测试才能得到的 ， 好吗 ？

**Rio** [1:32:15]
OK， 对 ， 我明白你的意思 。 就这个是其实对应的软件的这个所谓的 unit test， 保证每一个结构 ， 就是每一个 component， 每一个组件是正确的嘛 。

**吴涛** [1:32:26]
呃 。

**Rio** [1:32:28]
是这意思吗 ？

**吴涛** [1:32:29]
差不多吧 ，但实际上软件的 unit test 更如果一定要在建筑里面找出一个对应的话 ， 可能更像是说 OK， 我为这个楼设计了呃一层 ， 然后我要在我就想起消息姐说的 ， 对 ， 你拿消息姐说的那个体育馆的意思吧 ， 就是她设计了一个体育馆 ， 然后这体育馆里面每一层要摆上 20 个厕所 ， 那 unit test 又更像是说把每一个厕所 ， 假如每一个厕所都可以做成一个预构

件的话 ， 呃把每一个厕所的预构件拿出来 ， 单独给它通上水通上电 ， 然后你进去使用一次 ， 然后看它能不能冲水 ， 呃以至或者说你进去用一次之后， 看看它有没有什么不合理的地方 ， 这才更接近一个 unit test。

然后最重要的一点就是世界上没有两栋建筑是一模一样的 。

**Rio** [1:33:33]
嗯哼 。

**吴涛** [1:33:34]
Wait a second。 呃 ， 脑中浮现出来 ，不 ， 脑中浮现出的这个社会主义国家里面那些非常 。

**Rio** [1:33:45]
一个小气氛建筑都是一样的 。

**吴涛** [1:33:47]
对 ，有个笑话说把你截到一个中国三线城市的郊区扔下来 ， 呃给你一个小时的时间让你找出自己是在哪个城市你是找不出来的 。

**Rio** [1:33:58]
哈哈哈 。

**吴涛** [1:33:59]
对 ， 呃 ， 啊 ， 软件里面可能也是很多软件都彼此相似 ，但是没有两个软件是彼此相同的 。 所以呃如果你不写测试的话 ， 很有可能在你认为这个软件的这一部分应该那样工作的 ， 这个想法本身就是没有办法验证 ，而且不成立的 ， 最终你会发现它是不成立的 。

嗯

， 另外一个问题就是有些软件是无关紧要的 ， 比如说你打一个 hello world， 然后你可能最后会漏了那个换行符 ， 或者是你把 hello world 打成了 hello， 呃这些都是无关紧要的 ，但是另外一些软件则是人命关天的 ， 比如说你呃你开着车那个控制刹车的部分 ， 或者是控制转向的部分 ， 如果这个部分的软件出了问题 ， 那很有可能是会死人的 。

就呃我们之前请到的那个元昊哥哥 ，他在呃他所在的那家 Electrobit 所做的工作之所以会非常强调测试 ， 就是因为他们的软件里面有四个人身伤害的标准 ， 如果没有记错的话 ， 第一个标准是这个软件如果出了问题 ，有可能呃这个标准的第一等级就是如果这个软件出了问题 ， 那可能会有一个人受伤 ； 第二等级是如果这个软件出了问题 ， 可能会有一个人死亡

； 第三个等级是如果这个软件出了问题 ， 可能会有多个人受伤 ； 第四个等级就是可能会有多个人死亡 。

你看看人家的这个人这个软件的危险标准是这么来的 ， 那在这样如果你是负责开发这样一个软件的话 ， 那可能不是可能 ， 就是任何级别的测试都是必不可少的 。

**Rio** [1:36:03]
所以所以其实面对这种我明我理解你说那个意思啊 ，其实面对这种所谓的 mission critical 的组件 ，不是更应该从源头上去解决它的问题 ，而不是依赖过度依赖于测试吗 ？

**吴涛** [1:36:15]
呃 。

**Rio** [1:36:16]
就是我其实我知道你想说 。

**吴涛** [1:36:18]
我刚才一直我一直在试图绕开你的问题 ， 就是你会你想说架好的架构可以取代测试 ， 呃 。

**Rio** [1:36:27]
不不不 ， 这里面有一层要再再解释一下， 就是说嗯 。

**吴涛** [1:36:31]
好的架构可以减轻对于测试的依赖 。

**Rio** [1:36:35]
我觉得就是一个验证一个软件正确性的方法有两个嘛 ， 一个是你测出它所有的输入 ， 所有的输出 ， 对吧 ？

如果它这个这个输入输出是一个有限集的话 ， 你看是不是符合你的预期吧 ， 就是暴力什么暴力穷举法嘛 。

但是另外一个方法就是说你跟它做那个逻辑分析嘛 ， 我们叫 formal verification 嘛 ， 就是你你给你给它一个描述 ， 说它应该怎么怎么样 ， 然后你通过一些正式的方法 ， 嗯哼 ，formal 这个叫什么来着 ， 对 ， 正式的方法 。

**吴涛** [1:37:08]
形式方法应该说 。

**Rio** [1:37:09]
对 ， 形式的方法去证明它确实是未按照这种情况没有特例没有考虑过的 ， 对吧 ？

**吴涛** [1:37:16]
嗯哼 。

**Rio** [1:37:17]
所以测试其实是在我说的前一种方法 ， 就是去看它的输入输出 ， 然后看我们选取一些点 ， 比如说一些比较奇怪的点 ， 看看会出现什么问题 ， 选取正常的点 ， 看它是不是产生符合我们预期的答案 ， 然后选择一些奇怪的点 ， 看看是不是出现我们预期的异常或者错误 ， 对吧 ？

但其实这个覆盖和有一个 formal verification， 就是正叫什么来着 ， 这不是这看不叫正式的 。

**吴涛** [1:37:44]
形式证明 。

**Rio** [1:37:45]
对 ， 形式证明的这个得出的结论是完全不具备像可比性的 ，因为一个是说我们有 50% 的不 ，5% 的把握证明它们应该没问题 ， 和和这边形式证明是说我们 100% 确定它不会出错 ， 你明白我意思吗 ？

**吴涛** [1:38:01]
嗯 ，但我觉得有两点 。 首先第一点是你通过形式证明 ， 呃 ， 知晓了这一个软件这样写应该没有问题 ，但是你仍旧没有办法确定说你写出来的就一定完全符合你的形式证明 ， 比如说你在某个地方多打了一个点 ， 或者是在某个地方把加号写成了乘号 ， 这些东西都是没有办法通过形式证明来唯一确认的 。

**Rio** [1:38:32]
可以吧 ， 如果你把那个 specification 写得足够 ， 嗯 ，但你可能说这个界限就比较模糊了 ， 对吧 ？ 如果这个 specification 就写得那么详细的 。

**吴涛** [1:38:43]
这不就是 BDD 吗 ？ 这不就是 behavior driven development 吗 ？ 这不就是测试先行驱动的一种特殊形式吗 ？

**Rio** [1:38:51]
嗯哼 。

**吴涛** [1:38:51]
然后其次第二点是 ， 呃 ， 做形式分析是非常花时间的 ，而现代 。

**Rio** [1:38:59]
而且很很多时候是不可能的 。

**吴涛** [1:39:00]
对 ，而现代软件里面有很大的一个问题就是你刚才说 ， 呃 ， 如果你知道自己想要什么 ，但问现在的问题就是在很多领域里面 ， 最终负责验收软件的那个人是不知道自己要什么的 ， 你只有把它做出来才能知道自己要什么 。

**Rio** [1:39:17]
就这个可能就是学院派和工程派做事情的不同的一个出发点 ， 我觉得 。

**吴涛** [1:39:22]
对 ， 这就是微型模型啊 ， 瀑布模型和这个螺旋模型就是敏捷模型最大的区别 。

**Rio** [1:39:30]
嗯哼 。

**吴涛** [1:39:31]
对 。

**Rio** [1:39:32]
你要解释一下吗 ？

**吴涛** [1:39:33]
呃 ， 这个好吧 ，有一个问题就是我没学过软件工程 ， 你学过软件工程吗 ？ 你也没学过吧 ？

**Rio** [1:39:41]
对啊 。

**吴涛** [1:39:42]
对 ， 本质上我是一个学通信的人， 然后我在这边 。

**Rio** [1:39:45]
本质上我不是学 CS 的人。

**吴涛** [1:39:46]
对 ， 好吧 ， 我就一直给你简简解释一下所谓瀑布模型 ， 呃 ， 的意思就是你就像盖房子一样 ， 啊 ， 一上来给你个蓝图 ， 呃 ， 你假设你是业主 ， 你就像对我的同事正在盖房子 ，他所经历的就是这么一个过程 。

首先你去一个设计师事务所 ， 啊 ， 说我买了一亩地 ， 然后我要在这亩地上盖一个房子 ， 然后呃 ， 设计师公司说行 ， 然后他拿来这个这个小区的规划 ， 比如说德国有些小区规定说房顶必须是尖的 ， 然后尖的这个角度必须是多少多少度以上 ， 呃 ，他拿了一大堆 regulation， 然后帮你看一遍 ， 说好 ， 呃 ， 根据这些 regulation 我可以给你 ， 呃 ， 三个房型 ， 然后

你看着三个房型 ， 然后看着三个房型的平面图 ， 看着三三个房型的效果图 ， 看着三个房型的内部结构图 ， 然后你说好 ， 我要我觉得这间房子太小了 ， 我要把它改大一点 ，blah blah blah， 然后经过这么一个过程 ， 你最终确定一个方案 ， 你要在这个方案上签字 ， 然后建筑公司 ， 呃 ， 这个设计公司把它交给他们认识的一个包工头 ， 然后包工头开始干 ， 然

后干上一段时间 ， 你隔一段时间去看一看 ， 然后这个 ， 呃 ， 你会看到他先挖一个坑 ， 然后打地基 ， 然后盖第一层 ， 盖第二层 ， 把预制板插上， 盖第三层 ， 然后， 呃 ， 外墙装修 ， 内装修 ， 最后水道渠绳 ， 这么一个 。

你拿到了 ， 你拿到一间和自己最初的图纸可能略有出入 ，但是基本上是你想象的那个样子的一个房子 。 这是一个在实体世界里面非常司空见惯的事情 ， 然后在软件工程的早期 ， 人们也的确是这样做的 ， 就是一开始就找一些最终会使用软件的人说哦 ， 你最终会拿到的软件可能是这个样子的 ， 然后你按这个按钮就会出现那个 ， 呃 ， 点这里就会做那个 ， 然后

按下这个按钮 ， 呃 ， 核核弹就会飞起来之类的 。

**Rio** [1:41:50]
哈哈哈 ， 就所谓的需求文档嘛 。

**吴涛** [1:41:53]
对 ， 首先你有一套需求文档 ， 就像房子的蓝图一样 ， 接下来软件工程的团队开始施工 ， 然后在这个施工过程中， 你是没有办法去

勒令他们停下来 ， 说不行 ， 我不要这套房子了 ， 我把它 ， 呃 ， 你给我扒了 ， 把它重新建一遍 ， 或者说不对 ， 这个地方我要本来我是三层楼 ， 然后我现在要改成五层楼 ， 这些都这些都是不行的 ，在那个美好的时代 。

**Rio** [1:42:18]
如果如果你是一个足够土豪的甲方 ， 好像是可以的吧 ？

**吴涛** [1:42:24]
呃 ， 如果是一个足够土豪的甲方 ， 你所面临的损失仍旧远远不如你从一开始就明确的知道自己要什么要来的 ， 当然这个 。

**Rio** [1:42:37]
没错没错 。

**吴涛** [1:42:38]
如果你要 。

**Rio** [1:42:38]
所以我觉得瀑布这个词用得很好 ， 就是你知道瀑布的水都是往下走的 ， 对吧 ？ 它不会再回去了 。

**吴涛** [1:42:44]
你是在这个瀑布模型里面的任何一步 ， 你都是回不了头的 ， 就像盖房子一样 。

**Rio** [1:42:50]
没错 。

**吴涛** [1:42:50]
呃 ，而反过来敏捷模型则是在软件蓬勃发展的 90 年代 ， 人们终于有了怎么说呢 ， 更终于有了更多的人可以有这个资本去 ， 呃 ， 买或者说订购一套属于他们自己的软件 ， 比如说一些小商贩啊 ， 一个小公司啊 ， 可以有自己的网 ， 可以有自己的网站 ， 或者是可以有自己专门的应用 ， 呃 ， 此时人们发生了一个问 ， 发现了一个问题 ， 就是早期的瀑布模型再也行不通

了 ，因为很多很多人是 ， 包括你和我都是那些都是对于 。

**Rio** [1:43:29]
不知道不知道自己要什么 。

**吴涛** [1:43:30]
对于自己的想象力和怎么说呢 ， 高估了自己的想象力 ， 同时又低估了自己的野心的这么一群人， 可以站在那边 。

**Rio** [1:43:39]
表表达能力了 。

**吴涛** [1:43:40]
对 ， 哈哈哈 ，有了一点 ， 呃 ， 资本可以来做一个项目的验收方的时候 ，他们你会发现这些人是完全没有办法在 ， 呃 ， 瀑布瀑布模型之下工作的 。

**Rio** [1:43:57]
无法验收 。

**吴涛** [1:43:58]
对 ， 你一开始给他跟他答应了好好的一些东西 ，他做了一半 ， 你给他看一个半成品的时候 ，他说我靠 ， 我要的不是这样的 ， 嗯 ，在这种情况之下呢 ， 呃 ， 人们就推出那种叫做 ， 呃 ，extreme program， 或者说啊 ， 对 ， 早期对 extreme program 又早于 agile， 感觉 ， 呃 ， 推出一种所谓 XP，也就是极限编程的这么一种理念 ， 就是在这种模型之下呢 ， 呃 ， 你一开始只问这个最终的客户

很小的一个问题 ， 就说啊 ， 比如说打个比方吧 ， 你希望你的网站是 ， 你希望你的网站基色是什么颜色的 ，他说哦 ， 蓝色的 ， 然后你好 ， 你写一个网页 ， 然后把这个背景换成某种蓝色 ， 说这样吗 ？

客户一看说我靠 ， 纯蓝色怎么这么丑 ，不行 ， 我要粉红色 ， 好 ， 马上就可以换成粉红色 ， 然后 。

**Rio** [1:44:54]
就算什么 ， 就也算是交互式编程了吧 。

**吴涛** [1:44:57]
对 ， 这就是一个非常非常小的迭代 iteration，在这个过程之中， 你首先确定了用户一个非常基本的需求 ， 然后你把这个需求实现出来 ， 实现出来这一部分最小的功能 ， 找客户去反馈 ， 客户他对你的反馈如果是正的的话 ， 你就可以继续做下去 ， 如果是负的话 ， 你就要改 ， 然后把整个软件工程的 ， 呃 ， 过程切分为很多很多这样的很小的迭代过程 ，

呃 ， 如果你画成一个图的话 ， 大概就是一个越做越大的软件不停的经历这样的 iteration， 那最终画出来就是一个大概螺旋形的这么一个 ， 哎 ， 应该怎么说呢 ， 进度图 。

**Rio** [1:45:40]
OK。

**吴涛** [1:45:40]
这就是我 ， 呃 ， 就是我刚才提到的瀑布模型和敏捷模型之间的区别 。 所以敏捷编程或者说 ， 呃 ， 极限编程所解决的问题就是如何应对需求的改变 ， 对吧 ？

**Rio** [1:45:55]
嗯哼 。

**吴涛** [1:45:56]
那怎么才能知道一个需求的改变有没有准确的在 ， 呃 ，不管是被更改的软件也好 ， 还是刚刚写出来的软件的那一新的那一部分里面正确的实现出来了呢 ？

那这个时候软件测试的意义也就凸显出来了 。 嗯

，也就是说 ， 比如说 ， 呃 ， 客户告诉你说这个地方我希望它在最终的成品里面一个按钮是在另外一个按钮的左边的 ， 那你就可以写一个测试去判断这个两个按钮的 ID，以及它们之间的相对位置是不是正的 ， 比如说右边这个按钮的 ID 的 X， 呃 ， 对 ，X 减去左边这个按钮的 X， 如果它是正的的话 ， 你就可以确定说这个按钮是在另外一个按钮的右边 。

嗯 ， 我觉得可以说正是 ， 呃 ， 敏捷的这个过程 ， 或者说整个软件工程向敏捷的这个方向所转移的这样一个

范式迁移 ， 导致现在这样一个 ， 呃 ， 人们比相对来说比较强调测试的这么一个状态 。

**Rio** [1:47:15]
所以其实如果归纳来讲 ， 就是说 ， 啊 ， 需求不明确 ， 然后这个就是形式证明不可能的情况下， 我们只能用测试来尽可能的保障我们在 ， 呃 ， 快速迭代中能够有一个相对稳定的产品质量 。

**吴涛** [1:47:34]
对 ， 就是因为 ， 呃 ， 测试会给你一个比较清晰的一个比较客观的 ， 呃 ， 关于你的这个软件产品的质量的反应 。

**Rio** [1:47:45]
嗯哼 。

**吴涛** [1:47:46]
呃 ， 所以才能让你有信心去执行一个比较敏捷的软件迭代的过程 ，因为 。

**Rio** [1:47:54]
对 。

**吴涛** [1:47:54]
很有可能说 ， 呃 ， 如果你不写测试的话 ， 你可能做了一部分 ， 呃 ， 却弄坏了另一部分 ，而直到你在最后给客户演示的时候 ， 这个 bug 才暴露出来 。

我们知道根据墨菲定律 ， 这种情况是永远会出会出现的 ，而书写足够多的测试以及 ， 呃 ， 执行所谓回归测试可以帮助你减少这种情况的发生 。

然后， 嗯 ， 另外一方面 ， 如果你一定要写测试的话 ， 首先你得写出能够被测试的代码 ， 然后这样一来 ， 你如果在写代码的时候会想到说啊 ， 这个地方要被测试了 ， 那你可能会强迫自己写一些比较干净的 ， 比较模块化的代码 ， 然后这也会才从另外一个方面去帮助你提升整个软件的可控程度以及整个软件的质量 。

然后我们刚才提到的第一个是所谓 ， 呃 ， 软件驱 ， 软 ， 呃 ， 测试驱动开发的这么一个概念 ， 就 ， 呃 。

**Rio** [1:48:58]
TDD。

**吴涛** [1:48:59]
对 ，TDD。TDD 是什么呢 ？ 就是人们一发现这个驱动 ， 呃 ，不 ， 测试是如此好的这么一个东西 ，以至于有些人朝这个 ， 呃 ， 比较原教旨主义的方向发展 ， 就说好 ， 那我们在写软件之前先写测试吧 ， 这就是 TDD。

**Rio** [1:49:21]
就是让测试成为需求的一部分 。

**吴涛** [1:49:24]
呃 ， 这还要更进一步了 ， 我们先说 TDD 吧 ，TDD 最基本的一个实践就是好 ， 我上来要写一个 Hello World， 呃 ，在我写 Hello World 之前 ， 我要先写一个测试来确定我将要写出来的程序能够输出 Hello World， 然后我再去写 Hello World。

这是一个非常 ， 怎么说呢 ， 一开始听起来会觉得有些疯狂的概念 ， 叫 ， 呃 ， 准确的说 TDD 的执行的三原则是一 ，在写出一个测试失败的单元测试之前 ，不写功能代码 。

这是对 ， 这是一个什么概念 ？ 就是哦 ， 我要写一行程序 ，但是在我写这行程序之前 ， 我先要写一个没有这行程序就肯定会失败的单元测试 。

**Rio** [1:50:16]
那你怎么测这个 Hello World？

**吴涛** [1:50:18]
呃 ，Hello World 实在是太 trivial 了 ， 比如说我之前很喜欢的一个 Kata， 就是 ， 嗯 ， 把阿拉伯数字转为罗马数字 ， 呃 ， 我要写这个 ， 比如说我面对一门新的陌生的语言 ， 比如说 Haskell 或者是 Swift， 呃 ， 我首先 ， 嗯 ， 可以用其他的语言来判断这个语言 ， 我将要学的这个语言所输出的是不是正确的 ， 比如说我知道阿拉伯数字的 1 会转为罗马数字的 I， 那我就先写

这样一个测试 ， 嗯 ， 这个程序运行之后， 它应该在屏幕上输出 ， 或者这么说吧 ， 这个我将要写的程序首先应该接受接纳一个文本文件 ， 里面是 1 到 1000 的罗马数字 。

**Rio** [1:51:07]
嗯哼 。

**吴涛** [1:51:08]
呃 ，sorry， 首先它应该接受一个文本文件 ， 然后输出另外一个文本文件 ， 然后我需要把它输出的这个文本文件和我的目标文本文件作为对比 ， 嗯 ， 比如说一开始这个一开始的文本文件里面只有一个 1， 然后在目标文件文本文件里面应该有一个 I， 当我准备好了这一切之后， 我才可以 ， 我才开始着手用这种新的语言去写 ， 呃 ， 我将要写的这个 ， 我希望写的

这个阿拉伯数字转成罗马数字的程序 。 好 ， 然后这个 TDD 的第二准则是只编写恰好能体现一个失败情况的测试代码 。

**Rio** [1:51:52]
嗯 ， 一个比较简单的例子就是说你可以判断说 ， 呃 ， 如果输入是阿拉伯数字 1， 那么输出必然是罗马数字 I。

**吴涛** [1:52:01]
对 。

**Rio** [1:52:01]
然后如果你如果你先给它一个 ，因为没有功能代码 ， 只是一个空函数 ， 对吧 ？

**吴涛** [1:52:06]
对 。

**Rio** [1:52:06]
那我觉得它输入什么出来都是空 。

**吴涛** [1:52:09]
对 。

**Rio** [1:52:10]
那么你知道这个测试会挂掉 。

**吴涛** [1:52:11]
对 ， 然后呢 ， 第三条准则是更变态 ， 说只编写恰好能通过测试的功能代码 。 这是什么概念 ？ 就是我们完成了刚才两步 ， 一 ，在实在写一个测试失败的 ， 呃 ， 单元测试之前不写功能代码 ， 好 ， 我写了功能 ， 我写了 ， 呃 ， 会让测试失败的单元测试 。

二 ， 我写了刚好只能通过 ， 呃 ， 刚好只能体现一个失败情况的测试代码 ， 好 ， 我给在左边的文件里面给了 1， 阿拉伯数字的 1， 右边的文件里面给了拉丁字母 I。

好 ， 第三条 ， 我只编写恰好能通过该测试的功能代码 。 我在新的程序里面写说 if input is 1 then output I 就可以了 ， 对吧 ？

**Rio** [1:53:02]
对 。

**吴涛** [1:53:03]
那这样一种比较变态的开发方法 ， 你仔细想一下 ，其实是很难让你让一个

神智正常的人去接受的 ， 对吧 ？ 比如说我刚才说的这句话说 。

**Rio** [1:53:21]
你是说 TDD 的进行者就是神智不正常吗 ？

**吴涛** [1:53:25]
我也想这个 ， 呃 。

**Rio** [1:53:27]
哈哈哈 。

**吴涛** [1:53:29]
好 ， 先让我把话说完 ， 就是如果你是一个神智正常的人的话 ， 你肯定知道如果输出是 ， 如果输出是 1， 直接输出 I 是一个非常蠢的主意 ，因为从一开始你把你就把自己限定在了一个

非常着眼于非常短视的这么一个鼠目寸光的状态 ， 就是你只看得到输出 ， 输入是 1， 然后也只输出 1。

**Rio** [1:53:57]
打个岔哈 ， 那个你觉不觉得这个方法特别适合外包团队 ？ 因为你给别人干活 ， 你先满足他的需求 ，他会插回去测嘛 ， 然后你干多了没有用 ， 你只要干得刚刚好就可以了 。

**吴涛** [1:54:12]
嗯 ， 事实上也的确是外包团队在最多的使用体验期 ， 我必须这么说 。

**Rio** [1:54:20]
好吧 。

**吴涛** [1:54:22]
呃 ， 对 ， 总之刚才你说的这句话其实是有道理的 ， 就是使用 TDD 的人神智都不太清楚 。 我心里其实是很认同这句话 ，因为 TDD 就好像安利一样 ， 就是你你只有深陷其中了 ， 你才会真正的感受到它的好 。

**Rio** [1:54:42]
嗯哼 。

**吴涛** [1:54:43]
而我刚才这句话绝对不是一个以一种 compliment 的方式来说 ， 就是因为我从来没有深陷其中过 ， 所以我从来不觉得它的好 ，但是 。

**Rio** [1:54:54]
OK。

**吴涛** [1:54:54]
Somehow someway 我也可以理解其用户者所持的这样一种观点 ， 就是别看你使用的这三个原则非常的愚蠢 ，但是到你开发一个大型软件的后期 ， 你会发现迁移范儿洞穴式的状况是非是经常有的 ，而如果你能坚持着用这种非常愚蠢的方法 ， 呃 ， 把每一个最为微小的修改都以测试先行的方式写出来的话 ， 你会发现到后期你犯一点点小错都可以马上被发现

出来 ，而 ， 呃 ， 所有这些被发现出来的小错保证了你的软件质量 。

**Rio** [1:55:34]
OK。

**吴涛** [1:55:35]
对 ， 然后刚才你说的这个 ， 呃 ， 一一上来就描述整个系统的 behavior， 那其实是 TDD 的更进一步 ， 叫做 ， 呃 ，BDD，Behavior Driven Development， 呃 ， 它的核心理念其实就是像你说的 ， 乃至于 ， 呃 ， 可以更进一步 ， 就是不是用代码 ，而是用一种比较 ， 嗯 ， 项目经理也能读懂的普通语言 。

**Rio** [1:56:02]
大白话嘛 。

**吴涛** [1:56:02]
对 ， 用大白话来 ， 呃 ， 近似于大白话的普通的简单的句子来 ， 呃 ， 描述出整个系统的状态 ， 或者不是整个系统 ，是整个组件的状态 。

**Rio** [1:56:14]
所以这个一个最最古老的例子就是那个创世纪 ， 对吧 ？

**吴涛** [1:56:18]
创世纪 。

**Rio** [1:56:19]
对啊 ，因为上帝说要有光嘛 。

**吴涛** [1:56:21]
There should be light.

**Rio** [1:56:22]
这边有光 。

**吴涛** [1:56:22]
对 ， 对 。

**Rio** [1:56:24]
这最早的 BDD。

**吴涛** [1:56:25]
嘿嘿 ， 说的没错 ， 只不过在 BDD 里面 ， 这个创始人和 ， 呃 ，不 ， 开发者和验收人是同一个人。

**Rio** [1:56:36]
哈哈哈 。

**吴涛** [1:56:37]
这是比较操蛋的一点 ， 就是上帝只需要说 ， 呃 ， 上帝看着这一切是好的就可以了 ，而不是 。

**Rio** [1:56:45]
验收通过 ， 合格 。

**吴涛** [1:56:47]
上帝的老婆看到这一切把上帝揍了一顿之类的 。

**Rio** [1:56:50]
哈哈哈

。

**吴涛** [1:56:53]
对 ， 你再写这个 BDD 的 ， 你说什么 ？ 太不严肃了 。

**Rio** [1:56:58]
对 。

**吴涛** [1:57:01]
Anyway， 我们两个都是不可 ， 我不知道你 ， 我是不可知论者 ， 所以圣经就是一部 bullshit。

**Rio** [1:57:08]
哈哈哈 。

**吴涛** [1:57:12]
对啊 ， 我希望没有 insult 到足够少 。

**Rio** [1:57:17]
我觉得已经发生了 ，但是 it doesn't matter。

**吴涛** [1:57:22]
OK， 对 ， 你在写这个 BDD 的 ， 呃 ， 测试行为描述的时候 ， 就很有那种上帝的感觉 ，play God， 你可以说 ， 呃 ，it should throw division by zero error when input is given by zero， 之类的句子 ， 然后， 呃 ， 比较了不比较比较牛逼的这个 BDD 的工具 ， 比如说 Cucumber， 对 ， 应该是 Cucumber， 呃 ， 可以让可以有一个工具可以自然而然的把你的这些对于 ， 呃 ， 整个组件的行为的描述转化为相应的测试代码 。

**Rio** [1:58:06]
嗯哼 。

**吴涛** [1:58:07]
然后自动的在你写出来之后帮你执行它 ， 这就是更进 。

**Rio** [1:58:12]
你不就是要用那个 NLP 的方式来去解析那些东西吗 ？

**吴涛** [1:58:16]
呃 ，其实是一个非常简单的 Regular Expression， 如果没记错的话 。

**Rio** [1:58:20]
OK， 就是用一些比较规则的结构去描述那个 。

**吴涛** [1:58:25]
首先你在写那个 Behavior Description 的时候 ， 就不能用完全的自然语言 ， 你你必须用一个用一些特定的句式 ， 就好像你说的那个 ， 你在知识思维去做什么事情的时候 ， 你必须用一个特定的范式的句子 ， 然后 TDD 的这个描述语言跟它比较相似 ， 就是你必须用一些特定的句式 ，it should 之类的 。

**Rio** [1:58:48]
对 ， 这其实你知道这这也是为什么比较讨厌这种 BDD 的那个 Test Suite， 叫 Test Suite 的一个原因 ， 就是感觉好像 AppleScript。

**吴涛** [1:58:59]
哈哈哈 ， 对 ， 看起来好像在写程序 ，但是又没有真正在写程序 。

**Rio** [1:59:05]
又不是 。

**吴涛** [1:59:06]
对 ， 然后你就很难去模糊到我要到底写一个什么样的语句才能够满足它生成一个可以被它执行的 Test Case 呢 ， 你就很郁闷 ， 你就不要搞这个了 ， 你直接给一个写个正常的语句好不好 ？

**Rio** [1:59:18]
对 ， 这可能就是怎么说呢 ， 呃 ， 编程语言们编程语言里面的恐怖谷里了 ， 就是你要么写非常非常贴近机器的编程语言 ， 你要么就直接用自然语言 。

**吴涛** [1:59:30]
对 ， 要不你就逻辑一点 ， 要不你就自就真的是在语言能分析上 ，但是你在这介于之间就不忠不息的 ， 这非常难说 。

**Rio** [1:59:39]
而且而且就是就是就是用 BDD 的进行者经常会在可能 Ruby 是这个算里面做的比较极端的吧 ，Ruby 啊 ，Scala 这种也好 ， 它会把那个 DSL 啊 ， 就是 Domain Specific Language 的特性用到极致 。

**吴涛** [1:59:54]
对 。

**Rio** [1:59:55]
你经常会发现一些匪夷所思的语法在那里用着 。 哎 ， 相相当坑爹 ， 对 。

**吴涛** [2:00:00]
谁叫他们灵活呢 ， 灵活有灵活的代价 。

**Rio** [2:00:04]
好吧 。

**吴涛** [2:00:06]
嗯 ， 对 ， 所以其实就可以过渡到我们的下一个重点 ， 就是为什么人们讨厌测试 ， 或者说为什么人们会觉得测试是可有可无的东西 。

嗯 ， 你为什么讨厌测试 ， 或者你为什么不喜欢写测试 ？

**Rio** [2:00:26]
因为我觉得吧 ， 就是刚才我讲我喜欢有一些确定性的形经过形式证明的东西 ， 就是说我写的这么一小段代码 ， 经过严密的理论推敲 ， 它是不可能出错的 ， 那我觉得这是好的 。

然后你看我突然一跳起跳起来跟我说 ， 哎 ，不对 ， 你这个太麻烦了 ，有些你做不到 ， 我这个代码有有 200 行长 ， 你怎么你怎么证明它 ， 对吧 ？

还有那个那个什么输入输入 ， 就是什么叫做 ， 啊 ， 非确定性的 indeterministic， 对吧 ？

**吴涛** [2:00:58]
嗯 。

**Rio** [2:01:00]
要不你怎么去去形式证明它 ？ 没有办法 ， 那么我们来个突然奇奇字写测试吧 ， 写一个就是写个 50 个 Unitest 这个这个 cases， 那可能覆盖到大多数常见和不常见的情况 ， 那然后你都都跑通了 ， 那我们觉得在心理上有一定的把握 ， 证明这个事情是可行的了 。

但是呢 ， 我还是有一种深深的不安的感觉 ， 总觉得哎呀 ， 那万一有一个情况没覆盖到怎么办 ？

然后我就觉得还是从逻辑上去一层一层分析它 ， 哪里方会出错 ， 哪里方会会跳出 ， 这样会比较好 。

当然这也是一个间接的原因 ， 导致为什么我不喜欢那个异常机制 ， 就是 exception mechanism，因为它会导致你那个逻辑那个那个 control flow 啊 ，是多重的 exit point， 对吧 ？

这样子会导致你整个这个状态是不干净的 ， 如果你状态不干净的话 ， 你就很难去那个什么用那个叫什么啊 ，formal verification 的方法去验证它 ， 或者说你很难用那个推理的方法去证明它是不可能出错的 。

**吴涛** [2:02:04]
嗯哼 。

**Rio** [2:02:05]
这是一就是一些相关的问题 ， 我觉得 ， 然后写测试是一个很痛苦的过程 。

**吴涛** [2:02:11]
对 ， 我觉得很难的一个原因就是 ， 呃 ， 为什么会说写测试是一个很痛苦的过程 ， 就是因为它它没有给你它它不会给你一种 achievement 的感觉 ， 就你你写测试是不会有成就感的 ， 你你不会觉得自己在创造新的东西 ， 你只是你只是在做一件 ， 比如说给别人批作业 ， 或者是 ， 呃 ， 写完了卷子之后在那边验算自己写的对不对 ， 这样一种 。

**Rio** [2:02:40]
对对对对 ， 就刚才我讲那个你写代码的时候 ， 你总你有一种创造的快感 ， 对吧 ？creation 的这种感觉 ， 对吧 ？

你就一种上帝的视角在那在里面 ， 然后你证明它的时候 ， 你有一种就我不知道有些人做数学题 ，他证明了一道很难的题 ，他可能会有一种快感 ，其实写那个就是写那个 formal verification 其实有类似的作用 ，但是你说写测试感觉就好像什么呢 ， 就为了证明到数学题 ， 你只拿个计算器在那按说先输入一个 5， 得出是 50， 结果是先输入一个 6， 得出是 600， 啊 ， 你

觉得哎 ， 这是对的 ， 一切都没错 ， 写了这么做重复做试了 100 次之后， 你觉得哎呀 ， 我这个过程应该是正确的 ， 我这个答案应该是正确的吧 ，因为我测试了 100 个 ， 觉得都是正确 ，但其实没有经过证明啊 ， 你还是不确定的 ， 就没有快 ， 没有那个成就感 ， 就是一个很机械的劳动 ， 我觉得 。

**吴涛** [2:03:28]
对 ， 呃 ， 另外一方面也是因为我们就是从来没有在哪怕科班出身的人都很难会说自己曾经在求学就学编程的过程中学得过 ， 呃 ， 怎样写测试 。

我我相信

应该现在没有哪个大学里面会专门开设软件测试这一个课程吧 ， 哪怕是 。

**Rio** [2:03:52]
会在那个 software engineer 里面作为一个使用的工具去去讲 ， 这个我有我有我有体会 。

**吴涛** [2:04:00]
啊 ，OK， 所以你还是偷偷上过软件工程了吗 ？

**Rio** [2:04:04]
没 ， 我我但是我做过助教 。 哈哈哈 。

**吴涛** [2:04:07]
啊哈 ， 原来如此 。

**Rio** [2:04:09]
对 。

**吴涛** [2:04:09]
对 ， 呃 ，但是科班出身的人可能有这样一个机会 ，但是那些自学成才的人可能就完全没有学过怎样才能写 ， 怎样怎样去写测试 ， 乃至于怎样写出可以被测试的代码 。

而我们必须承认的也是 ， 哪怕对一个很就编程编的相对熟练的人来说 ， 你让他 ， 呃 ， 去去适应一个把所有代码都写得 ， 呃 ， 易于测试的这么一个写出易于测试这么一个风格来 ， 呃 ，也其实挺难的一件事情 。

**Rio** [2:04:44]
嗯哼 。

**吴涛** [2:04:45]
就 ， 嗯 ， 尤其是有时候可以测试的代码跟不啰嗦的代码其实是非常相彼此抵触的这么一个一个一个一个状态 ， 就是有时候也许你可以判断一个条件 。

**Rio** [2:05:00]
测试必然啰嗦呀 。

**吴涛** [2:05:02]
啊 ， 可测试的代码必然是啰嗦的 ， 测试本身当然是就是完全是不必要的废话 ，但可测试的代码为了保证其可测试性 ， 可能要比不可测试的代码啰嗦很多 ， 比如说可能有一个边界条件 ， 你要去检测这个边界条件 ， 同时根据这个边界条件给某一个数值 ， 呃 ， 同时根据这个边界条件去改变某一个数值 ， 那如果你不需要写测试的话 ， 你可以直接

测试 ， 呃 ， 直接去测验这个验证这个边界条件 ，并且同并且马上再改数值 ，但如果你要为了把这个这一部分的功能做得可以测试的话 ， 你可能会要你可能会需要把那个修改数值那一部分单独立出去 ， 专门去测量 ， 先去先来测量一下这个边界条件 ， 对 ， 诸如此类等等 ， 都让人觉得何必呢 。

**Rio** [2:05:56]
哈哈哈 ， 那刚才那个提到那个你说科班那个培养的培训练的都没有训练这个写测试代码 ， 我想补充一点啊 ， 就刚才我讲哪怕是就我我做过这个软件工程这种课的助教 ， 我去看了他们那些培训 ，其实我的感觉在现在的大学的教育里面还是没有把这个事情放到一个非常重要的地位上来去讲 ， 可能一方面是因为大学的一个一个定位吧 ， 就它并不是说变我不

是一个 vacation school，vacational school 就是不是一个职业技术学院 ， 对吧 ？ 我并不是要培养出一帮产业工人能够上线直接用的 ，而是说培养一种思维 ， 这种是这种定性的方这个这个这个这个这个出发点会导致他们会轻视就重视原理 ， 轻视实践 ，而测试属于那种实践远远超过原理的东西 ， 就哪怕是在现在的一些大学里面开软件工程的课里面 ，他对测试怎么写都只是提

前说 ， 呃 ， 我再给你展示几个案例 ， 然后你们剩下的原理你自己去看数据吧 ， 我给你讲一些大的原则 ，但并不会告诉你 ， 实话实的告诉你怎么去实操这个东西 ， 所以这也难怪你说就哪怕是科班出身的 ，他也不会有特别好的这种那种实践的经验去写测试 。

**吴涛** [2:07:06]
呃 ，其实也就牵扯到另外一个问题 ， 就是作为工程学的计算机软件 ，其实可以作为一种匠艺 ， 就是所谓的 ， 呃 ，craftsmanship， 呃 ， 它其实更适合要使用这种就是工匠制或者说学徒制的方法来传授 ， 啊 ， 强调实践 ， 强调 ， 呃 ， 经验的传承 ， 强强强调手把手 ， 比如说敏捷编程里面有一个很强很重要的原则就是节律编程 ， 呃 ， 两个程序员共用一个键盘 ， 共用一个共

用一个鼠标 ， 共用一个屏幕 ， 这其实是同样也是就像 ， 呃 ，TDD 那三个原则一样 ， 非常难以接受的一件事情 ，但是其就是会就像安利一样 ， 喜欢它的人会觉得它是非常非常好的一个一个实践原则 ， 那 ， 呃 ，在大学里面所进行的软件工程的教育可能会比较流于理论 ，因为 ， 嗯 ， 毕竟在很多时候教授软件工程的教授本身可能完全没搞过软件工程 ，他是一个比较从相对的从相

对来说比较学院派的角度去 ， 啊 ，在向学生传授一个自己想象之中的软件工程是怎样实施的 。

**Rio** [2:08:29]
对 。

**吴涛** [2:08:29]
这是这是为什么测试一直没能得到 ， 嗯 ， 足够的在课堂里面的重视的原因之一 ，因为它本身就不适合不适合于课堂 ， 应该这么说 。

**Rio** [2:08:41]
对 。

**吴涛** [2:08:44]
啊 ，其实这还让我想到另外一个问题 ， 就是 ， 啊 ， 我不知道你的感观是什么样 ， 就是我好像印象里面很多女孩子都会在毕业之后如果进了软件公司的话选择去做测试 ， 这是为什么呢 ？

**Rio** [2:09:00]
哎 ， 这个事情我也是很好奇 ，因为之前在知乎的时候 ， 我们最早的那个测试的工作也是一个就一个女孩子在那边做嘛 ， 可能有一种传统上认为说女生会心细一些 。

**吴涛** [2:09:16]
我觉得这是一某种歧视 ，somehow someway。

**Rio** [2:09:19]
我也觉得是 ，但是 。

**吴涛** [2:09:20]
就是好像你就像好像觉得 ， 啊 ， 测试是一个没有创造力然后又非常需要心细的人去做 。

**Rio** [2:09:28]
就如果即便不算歧视的话 ， 至少是一种偏见 ， 我觉得 。

**吴涛** [2:09:31]
对 ， 它它 somehow 带了一个默认的性别偏见 ， 就是它觉得 ， 呃 ， 女性适合于做这种

括号没然后没有什么技术水准的活 。

**Rio** [2:09:46]
测试 ， 哎 ， 好吧 。

**吴涛** [2:09:49]
但其实测试是相当有技术水准的 ， 如果你要把 。

**Rio** [2:09:51]
对啊 ， 我觉得要写好一个测试的那个 test case 才是蛮多事情要考虑的 。

**吴涛** [2:09:58]
对 。

**Rio** [2:09:58]
但不过这里面有些测试就是说是一个刚才你说 smoke test， 就是它甚至不会去接触到源码 ， 只会说测试成品怎么样 ， 就是另外一种形式的测试 ， 跟我们今天讲的那个单元测试还不是一个一个东西 。

**吴涛** [2:10:10]
嗯哼 。

**Rio** [2:10:11]
对 ， 那这就不展开讲了哈 。

**吴涛** [2:10:13]
对 ， 这个有兴趣的或者说对此有感触的听众 ， 欢迎你写信来谈一谈你所遇到的 。

**Rio** [2:10:21]
开启一个吐槽模式 。

**吴涛** [2:10:22]
对 ，是不是很多 ， 乃至于我相信也许我们的听众里面的确有很多做测试的女孩子 ， 女女性听众 ， 嗯 ，不妨也谈谈你为什么会选择去做测试 ， 乃至于你觉得测试真的比较适合女性吗 ？

**Rio** [2:10:41]
然后你觉得你有这个过程中你有成就感吗 ？

**吴涛** [2:10:44]
对 ， 欢迎来信 ， 啊 ， 长短不限 。 嗯 ，OK， 那根据提纲 ， 我们接下来要讲到的是一系列 ， 呃 ， 和单元测试相关的工具 ， 就是 ， 嗯 ， 本意也是希望对测试感兴趣的 ， 啊 ， 听众可以 ，而对测试没有足够多经验的听众可以去找一些就可以去搜一些相关的工具 ， 然后看一看他们是怎么使用的 。

总之 ， 呃 ， 进行到下一个环节之前 ， 我们可以最后来吐槽一下这个 TDD 了 ， 我觉得 。

**Rio** [2:11:21]
哈哈哈 ， 火力全开 ， 来吧 。

**吴涛** [2:11:24]
对 ， 我觉得 TDD 非常印度 。

**Rio** [2:11:27]
非常呢 ？

**吴涛** [2:11:28]
非常印度 。

**Rio** [2:11:30]
呃 ， 这怎么讲 ？

**吴涛** [2:11:32]
这是一个非常地图炮而且地域歧视的说法 ， 就是 ， 呃 ，TDD 是一个 ， 呃 ， 为了保证质量而忽视了

， 呃 ，而压抑了人的创造性的这么一个软件方法 ， 就是你可以说 TDD 的出现是历史的必然 ， 就好像 ， 呃 ， 福特 T 型车会在会以流水线的方式来生产是历史的必然一样 ，但是也正是因为 TDD 或者说流水线的出现 ， 啊 ， 这种所谓 mass production 的出现 ， 啊 ， 导致了

human 变成为 human resource， 就是 。

**Rio** [2:12:19]
哈哈哈 。

**吴涛** [2:12:20]
我这么说可能扯得有点大 ，有点形而上 ，但 。

**Rio** [2:12:26]
没没有 ， 我觉得这个很好 ， 我觉得这个点很好 ， 就是如果你看一个公司一旦出现了 HR 这个部门之后， 这个同事通这个公司通常都会都会有一点点问题了 。

**吴涛** [2:12:37]
对 ， 我就好像 ， 呃 ，Benz 在开发第一辆车的时候 ， 它显然不会给每一个零件做测试 ， 啊 ，AT&T 贝尔实验室的黑客们在一开始写第一版 Linux 的 ， 呃 ，Unix 的时候肯定也不会去写单元测试 ， 呃 ， 真正具有创造性的工作是不会写测试的 。

**Rio** [2:13:04]
哈哈哈 ， 就我觉得 TDD 最大的问题就是在于它打破了那个创造的这个所谓的流 flow 啊 ， 就是比如你在想你在做一件很投入很有创造性的事情 ， 你会在进入一种状态 ， 那状态你会持续做去做一个创造性的工作 ， 去构建一整套的东西出来在头在脑海中， 然后把它落实到笔头也好还是键盘上也好 ， 把它变成一个实体的物件 ，但是 TDD 其实是把这个

流给切成无数无数的碎片 ， 然后你不断的在这个跳里面跳来跳跳出跳入跳出去写那个测试 ， 然后再跳回来创造 ， 整个这个 flow 就已经没有了嘛 。

**吴涛** [2:13:43]
对 ， 整我觉得在 TDD 的整个过程里面唯一爽的人其实就是架构师或者说是那个拆分工作的人。

**Rio** [2:13:51]
没错 。

**吴涛** [2:13:51]
他是唯一一个有创造性的角色 。

**Rio** [2:13:53]
对 ，他把那个什么蓝蓝 blueprint 那 blueprint 都给你画好了 ， 然后你说那个什么你们这些 ， 啊 。

**吴涛** [2:14:01]
包工头 。

**Rio** [2:14:01]
Human resource， 对 ，human resource， 什么什么包工头 ， 你们这些小工照这个图纸干就好了 ， 你们如果干不好我随时可以换一个人。

**吴涛** [2:14:10]
没错 ， 对 ， 就好像在建筑领域里面 ， 一个建筑造了再美轮美奂 ， 再功能完善 ， 人们也只会记住建筑师的名字 ，而不是你这个搬砖的小工的名字 。

**Rio** [2:14:23]
对 。

**吴涛** [2:14:23]
对 ， 这就是为什么我看到任何一个 ， 嗯 ，enforce TDD 的公司都会觉得 ， 啊 ， 简直是 living high living hell。

**Rio** [2:14:35]
能躲就躲是吧 。

**吴涛** [2:14:36]
对 ， 这其实让我想起来前阵子刘一说 ， 呃 ，在有一期 ， 呃 ，IT 公论里面你们提到一个独立游戏开发者说 ， 呃 ， 什么去 EA 或者是去 EA 这样的大公司大的游戏公司简直就是 hell。

**Rio** [2:14:52]
对对对 ，有类似的原因 。

**吴涛** [2:14:54]
对 ， 它的道理其实就是你在那个这样的公司里面扮演的其实就是一个流水线上的工人， 然后你 。

**Rio** [2:15:01]
斯蒂玛 ， 传说中的 。

**吴涛** [2:15:02]
对 ， 你的个性被抹杀了 ， 你成为了一个 human resource， 然后你唯一出现的就是那个最终的演职员表里面一个没有大部分玩家都会立刻按 A 去跳过的这么一个字幕里面的一部分是 。

**Rio** [2:15:18]
不过不过这件事如果反过来讲呢 ，也可以说这样才可以保证出品的稳定嘛 ， 对吧 ？ 如果 。

**吴涛** [2:15:24]
对 ，也只有采用这样的方式 ，也只有采用这种不信任人让人成为可以被替换的零件的方式 ， 才可以做出规模足够大的东西 ， 这个我是毫不否认的 。

**Rio** [2:15:36]
而且就是能保证这个它的出品是稳定的 ， 就好像为什么老是我们老是吐槽说中餐难以标准化 ， 就是因为它的那个出品不不够稳定 ， 你换一个人换一个厨师就可以 ， 或者换甚至换一种调料这个事情就就就就口味就变掉了 ， 所以我就是在想这个到底是一个怎么样的情况 ， 怎么能才能够拿到两者的好处 ， 同时避免两者的短板 ， 好像现在

看来没有什么太好的解决方案 。

**吴涛** [2:16:03]
我觉得一个解决方案可能就是人工智能吧 ， 就是因为 TDD， 呃 ， 可能现在 TDD 还太原始 ， 就是假如将来我们可以直接先给出所有的边界条件 ， 然后让 AI 自己去帮我们写出程序来 ， 那可能 ， 啊 ， 到那个时候我们也就不需要再为这种事情发愁了 ，因为 。

**Rio** [2:16:24]
其实这个已经也有了 ， 这个所谓的什么第四代编程语言不就做这种事情吗 ？ 人指定一个 constraint， 然后他自己去去去解决这个 con 怎么去找到满足这个 constraint 的一个解 ，但是效率是很成问题的 。

**吴涛** [2:16:40]
呃 ， 对 ， 然后这个就又 ， 呃 ， 跟我们之前提到的那个

the rabbits 还是 ， 嗯 ， 那个网站叫什么来着 ？

**Rio** [2:16:51]
啊 ， 那个带 。

**吴涛** [2:16:52]
对 ， 带 。

**Rio** [2:16:53]
带工艺的 。

**吴涛** [2:16:53]
带你写代码那个 。

**Rio** [2:16:55]
我也忘了 。

**吴涛** [2:16:55]
叫什么来着 ？

**Rio** [2:16:57]
对 ， 反正和兔子有关 。

**吴涛** [2:16:59]
对 ， 然后还有 。

**Rio** [2:17:00]
叫 the rabbits 吧 。

**吴涛** [2:17:02]
OK，the rabbits， 呃 ，以及和之前和慕瑶聊到的没能跟慕瑶聊起的那个话题就是 ， 啊 ， 计算机可以做数可以做数学嘛 ， 计算机可以做出计算机可以设计出来一个有创造性的算法嘛 ，其实也是目前现阶段看来不太可能 ，也是就是 ， 啊 ， 我们也许可以通过 TDD， 呃 ， 通过第四代第五代计算机语言来完成一些枯燥的只有现阶段只有依靠 TDD 或者 BDD 才可以达到的 ， 呃 ， 大规模软件 。

**Rio** [2:17:39]
就所谓的穷举法证明嘛 。

**吴涛** [2:17:42]
对 ， 呃 。

**Rio** [2:17:43]
哎 ， 说这个其实已经有像 TDD 那个证明那个叫什么来着 ？ 啊 ， 地叫什么 coloring problem 是吧 ？ 地图填色的那个那个难题 。

**吴涛** [2:17:52]
哦 ， 四色四色定理 。

**Rio** [2:17:54]
对 ， 四色定理那个好像不是证明出来吗 ？ 就是靠暴力破解 。

**吴涛** [2:17:57]
对 。

**Rio** [2:17:58]
对啊 ， 就这个就是 T 就是什么数学领域的 TDD 吧 。

**吴涛** [2:18:01]
对 ， 呃

，也不尽然 ，但对 ， 各位理解这是什么意思就好 。

**Rio** [2:18:10]
嗯 ， 对 ，有有神似之处 ，但并不是一回事 。

**吴涛** [2:18:13]
对 ， 另外一个我又想起来一个暴力的方法 ， 就是 ， 嗯 ， 说最近 ， 呃 ， 近一段时间围棋的 AI 有比较大的提升 ， 就是因为他们采用了一种比较暴力的算法 ， 就是穷举所有 ， 呃 ， 用蒙特卡洛算法 ， 啊 ， 随机的去随机的去去采用一些可能的走法 ， 然后从里面找出来一个 ， 呃 ， 效果最好的 ， 然后成功的让业余棋手基本上没有人能够下过这个围棋算

法 。

**Rio** [2:18:48]
OK。

**吴涛** [2:18:49]
回头可以把相关的那个报道找出来看看 ， 对 ， 大概就是这么一个意思 。 嗯 ， 对 ， 我觉得 TDD 是一个

是历史的必然 ，但就好就好像这个汽车的生产线 ， 呃 ， 可能还有一些地方是在用手工 ，但至少在德国基本上四大车厂全都是在用机器人来完成那些以往需要人类才可以完成的流水线工作 ， 将来我觉得 ， 呃 ， 这些比较低级的代码的验证乃至于生成工作应该是可以交由人工智能自动完成的 ， 所以这就是我为什么说 TDD 非常印度 ， 就是因为印度加引号 ， 我只不过不愿

意说中国 ， 就是在这个第三世界国家 。

**Rio** [2:19:42]
确实是很印度啊 ，因为那个亚马逊那个 mechanic Turk 好像那些服务商都在印度吧 。

**吴涛** [2:19:49]
但这种说法比较怎么说政治不正确 ，但是我们也没有在追求政治正确 ， 所以 。

**Rio** [2:19:54]
对 。

**吴涛** [2:19:55]
一言下之意就是在第三世界国家这种 ， 呃 ， 密集脑力劳动的产业链的这样一个环节 。

**Rio** [2:20:04]
这还算脑力劳动 ， 这个算体力活了吧 ， 已经 。

**吴涛** [2:20:08]
脑区分脑力劳动和体力劳动的区别只是你用不用敲键盘吧 ， 我觉得 。

**Rio** [2:20:12]
哈哈哈 。

**吴涛** [2:20:13]
TDD 还是要敲键盘 ， 所以还是对 ， 嗯 ， 只有在这样一个环节里面才 。

**Rio** [2:20:19]
对 ， 我相信在印度这这帮人还是会定会定性为高科技产业的 ， 对 。

**吴涛** [2:20:24]
那肯定 。 但是这种说法其实也比较偏激或者说比较 cynical，因为其实在美国在在欧欧美还是有大量的企业会采用类似于 BDD 的方法来开发自己的软件 ，而且 ， 呃 ， 即便硅谷的这些当红炸子鸡们也是有很多会非常强调 ， 我相信 Facebook 也是一个非常非常强调测试的公司 。

**Rio** [2:20:53]
嗯哼 。

**吴涛** [2:20:54]
苹果就微软就不用说了 ， 微软据说有一个非常非常非常非常大的测试部门 。

**Rio** [2:21:03]
他们不是整个公司都是测试部门吗 ？

**吴涛** [2:21:06]
这样不好 。

**Rio** [2:21:07]
都在测试那个 Windows 10 的 beta 不是 alpha。

**吴涛** [2:21:11]
嗯 。

**Rio** [2:21:12]
之类的 。

**吴涛** [2:21:13]
所以苹果是不怎么喜欢写测试的吗 ？ 你觉得 ？

**Rio** [2:21:16]
Who knows？ 看他们出品出品的这个质量应该是不写了吧 。

**吴涛** [2:21:20]
对 ， 啊 ， 当然不 ， 毕竟毕竟这一次 WWDC 上发布的这一系列

在怎么说呢 ，在偿还他们的技术债务的这个补丁我觉得还是比较好的 ， 就是 ， 嗯 ， 软件质量至少在 ， 呃 ， 这代叫什么 el capitano 在这一代 。

**Rio** [2:21:42]
El capitano， 对 。

**吴涛** [2:21:43]
对 ，在这一代 。

**Rio** [2:21:45]
没有新没有太大的新特性嘛 ， 对 。

**吴涛** [2:21:47]
对 ， 所以就说明了他们把时间都花在了修 bug 上面 。

**Rio** [2:21:52]
那也不一定 ， 你可能在搞什么 watchOS 之类的事情 。

**吴涛** [2:21:56]
I don't say。 好吧 。

**Rio** [2:21:59]
就是不要太乐观 ， 我觉得 。

**吴涛** [2:22:01]
嗯 ，OK， 呃 ， 所以我们接下来可以进入到本期的最后一个环节 ， 就是介绍一些常用的 ， 啊 ， 写测试的工具 。

**Rio** [2:22:12]
嗯哼 。

**吴涛** [2:22:13]
呃 ， 尤其是 unit test， 就是单元测试 ， 单元测试是所有的你所能写的测试里面最颗粒最小的一个 ， 同时也是作为一个开发者而不是 ， 呃 ，QA 人员 ，也就是软件验收者来说所能接触到的最普最常见的一种测试 。

### 测试工具

**吴涛** [2:22:32]
首先要介绍给大家的就是 XUnit family， 呃 。

**Rio** [2:22:36]
哈哈哈 。

**吴涛** [2:22:38]
怎么说呢 ， 就是因为单元测试 。

**Rio** [2:22:40]
插单元 。

**吴涛** [2:22:40]
对 ， 插单元 。

**Rio** [2:22:42]
插组 。

**吴涛** [2:22:42]
Family， 呃 ， 就是因为软件测试单元测试非常非常的普遍 ，以至于有这么一套 ， 啊 ，pattern 可以被套用在各个语言所写的程序里面 ，而这个 pattern 在最开始的创始人， 呃 ， 是一个叫做 Kent Beck 的

大神 ，他应该也算大神里面 ， 呃 ，而他最开始所写的这一套 ， 呃 ，unit test 的 ， 呃 ， 工具呢是叫做 SUnit， 啊 。

**Rio** [2:23:21]
是 sum it。

**吴涛** [2:23:22]
Small talk 用 ， 跟 sum。

**Rio** [2:23:24]
Sum it。

**吴涛** [2:23:25]
对 ， 跟 sum 没什么关系 。

**Rio** [2:23:26]
至少至少是 sun it。

**吴涛** [2:23:29]
啊 ，OK， 你是说它是可以念出来的是吧 ？sun it。

**Rio** [2:23:33]
我觉得 sun it。

**吴涛** [2:23:35]
OK， 所以 JUnit 应该怎么念 ？John it。

**Rio** [2:23:39]
John it。

**吴涛** [2:23:40]
哈哈哈 。

**Rio** [2:23:42]
OK。

**吴涛** [2:23:43]
怎么像 Jennet。

**Rio** [2:23:44]
哈哈哈 。

**吴涛** [2:23:45]
而而 RUnit 就是 ruin it， 毁了它吧 。

**Rio** [2:23:50]
不是 run it 吗 ？

**吴涛** [2:23:52]
OK， 嗯 ， 对 ， 我还是倾向于把它念成 SUnit，sun it。

**Rio** [2:23:58]
嗯 ， 对 ， 这个是一个正确的念法 。

**吴涛** [2:24:00]
OK， 呃 ，Kent Beck 这个人呢为 ， 呃 ，small talk 所研发出的这一套 ， 呃 ， 单元测试的工具 ， 呃 ，在紧紧跟随着这个极限编程的方法以及整个 ， 嗯 ， 向敏捷转向的这么一个软件工程的潮流 ， 逐渐被套用到了其他所有几乎所有语言上面 ， 甚至几乎这两个字都不用加 ， 就是除了什么 brainfuck 之外， 呃 ， 可能没有不支持 unit test， 呃 ，不支持这个 XUnit 的 ， 呃 ， 语言存在 ， 就是 。

**Rio** [2:24:35]
嗯 。

**吴涛** [2:24:36]
基本上你能想出来的什么 C 啊 ，PHP 啊 ， 嗯 ，Ruby 啊 ，Java 啊 ，Java 就更不用说了 ，JUnit 简直是 Java 世界里面 ， 呃 ， 如果你想要找到工作一定要学这么一个工具 ， 然后， 呃 ，Docnet 世界当然也有相应的 ， 比如说 NUnit 或者是 ， 呃 ， 微软自家出的之前叫 MS test， 后来改叫 VS test，Visual Studio test。

**Rio** [2:25:04]
嗯哼 。

**吴涛** [2:25:04]
嗯 ， 然后如果你使用 ， 嗯 ，objective C 的话 ， 之前有这个所谓 XC test，XC stands for Xcode， 对 ，XC test 就好像 VS test 一样 。

**Rio** [2:25:20]
嗯哼 。

**吴涛** [2:25:20]
是在 Xcode 里面执行的 ， 嗯 ， 专门为 objective C 以及 ， 啊 ，Swift 应该也有 ， 所开发的这个单元测试框架 。其实这边直接给一个这个链接就好了 ，因为 Wikipedia 上有一个比较好的 ， 嗯 ， 呃 。

**Rio** [2:25:39]
叫做 list of unit testing frameworks。

**吴涛** [2:25:42]
List of unit testing frameworks， 对 ， 然后， 嗯 ， 这个我们想要说的一个比较有意思的东西其实是 doctest， 就我不知道你用没用过 ， 嗯 ， 就是 Python 语言里面有一个 ， 啊 ， 当然有一个 unit test 包 ， 然后另外 Python 有一个很有意思的包叫做 doctest， 呃 ， 你用过吗 ？

**Rio** [2:26:05]
没有 ， 一个不写测试的 。

**吴涛** [2:26:08]
嗯 ， 哈哈哈 。 呃 ， 这里比较想要安利一下的东西就是 doctest 这个东西 ， 它它有意思或者说它它实用的点在哪呢 ？

就是我们知道 ， 呃 ， 如果你在一个方法或者在一个类里面 ， 啊 ， 它的定义下面直接写一个 string， 呃 ， 这个东西被当被称为 docstring 是吧 ？

**Rio** [2:26:32]
啊 ，OK。

**吴涛** [2:26:34]
然后你可以在这里 。

**Rio** [2:26:35]
我想起来我有我有我有我有见到过这个 ，但自己没有试过 。

**吴涛** [2:26:39]
OK， 然后 doctest 这个包所支持的一个功能就是你可以在这个 docstring 里面写一些测试 ， 呃 ， 语法很简单 ， 就是 ， 呃 ，Python 的这个提示符大家都知道是三个相应的大于号对吧 ？

**Rio** [2:26:56]
嗯 。

**吴涛** [2:26:56]
那么你只需要在这个 docstring 里面写三个相应的大于号 ， 然后写 ， 啊 ， 这个测试所应该执行的语句 ， 然后在新令启行在不写这个三个大于号的情况下写出这个程序执行之后所应该有的值 ， 你就写好了一个测试 ，是不是很神奇呢 ？

就好像你在这个 docstring 里面给你的这个函数写了一个 ， 啊 ， 用法的示例 ， 然后这个示例本身 ， 哎 ， 忽然就可以当作单元测试来用了 ， 对 ， 这是一个非常好的一件 ， 呃 ， 一个一个一个工具 。

**Rio** [2:27:34]
但我觉得这个的唯一的问题就是有时候那个力度 ， 就是它不是一个 unit 的时候你就没法用这个方法了 。

**吴涛** [2:27:42]
对 。

**Rio** [2:27:42]
就这个就 doctest 仅限于 unit test 用 。 一旦一旦跨了一个函数就不行 。

**吴涛** [2:27:49]
其实也是有别的方法 ， 比如说 ， 嗯 ，doctest 这个包可以单独拿出来就是生成一个专门的 Python 文件 ， 然后这个 Python 文文件里面除了这样以 doc， 呃 ，test 的语法写成的测试之外别无他物 ， 然后你可以在这个里面 ， 呃 ， 用这个 doctest 来或者说滥用 doctest 来写一些跨模块或跨函数乃至于跨模块的测试 。

**Rio** [2:28:18]
嗯哼 。

**吴涛** [2:28:19]
呃 ，Zop 有一个测试框架就是干这个 。

**Rio** [2:28:23]
哈哈哈 。 不过这个这个 doctest 其实有点像那个叫什么 Donna Cruise 的那个叫 literary programming 翻译出来的 。

**吴涛** [2:28:33]
Literary programming， 嗯 ， 对 。

**Rio** [2:28:34]
Literary programming 中翻译叫什么来着 ？ 文化编程 ， 文艺编程 ， 文青编程 ， 哈哈哈 。

**吴涛** [2:28:42]
文艺编程 。

**Rio** [2:28:43]
我不知道这个怎么翻 ， 怎么翻译 ， 就就它那个东西就是说其实就是在就是其实一直在写注释 。

**吴涛** [2:28:50]
对 。

**Rio** [2:28:50]
代码就是穿插在 。

**吴涛** [2:28:52]
你用写注释的方式来写代码 。

**Rio** [2:28:54]
没错 ， 然后这个就是有点反过来就是说 ， 呃 ， 你也主要是写代码 ，但是注释呢是对代码的一个解释 ， 然后这个解释还是可以还是可以执行的 ， 这点还比较不错 。

**吴涛** [2:29:06]
最后一个问题就是 ， 嗯 ， 现在正夯的一个 functional programming 的概念 ， 呃 ， 我们知道在敏捷方法崛起的过程中其实基本上也就伴随了伴随着面向对象这个思潮的崛起 ， 嗯 ， 基本上可以说如果没有面向对象理念的话 ， 敏捷是完全实现不了的 ， 那面对面向对象编程也已经被证明了是更适合于写测试的一种方法 ， 呃 ， 那我们可以把 。

**Rio** [2:29:40]
它封装得好 ， 封装得好嘛 。

**吴涛** [2:29:42]
对 ， 呃 ， 面向对象可以保证你把系统的耦合度降到最低 。

**Rio** [2:29:48]
嗯 。

**吴涛** [2:29:49]
嗯 ， 那么相同的问题我们可以套用在目前正夯的这个 functional programming 的概念上， 呃 ，functional programming 适合写测试吗 ？

**Rio** [2:30:02]
其实我觉得还蛮合适的啊 ，因为怎么说呢 ， 就是 functional programming 的一个思潮就是说每一个函数的独立性很好 ， 就是它至少就是在在就在原则上我们是鼓励每个函数是可以叫做它是认识一个函数对吧 ， 所谓函数就是说它是确定输入 。

**吴涛** [2:30:22]
没有负作用 。

**Rio** [2:30:23]
对 ，side side effect free， 就是我确定一个输入就确定一个输出了 ， 这个时候你写测试就比较简单了 ，因为你不用考虑说你从某一种状态进入这个函数或者进入一个过程的时候会得到一个一个一个解 ，但是你从另一个状态进入的时候得到另外一个解 ， 就你这个这样的话 ， 你这个单元测试没法写了嘛 ， 对吧 ， 你得去先就是叫 set up the environment， 你得先设置这个环境才可以

，但是如果是 FP 的话就不存在这个问题 ， 你只是你只用照着写什么输出给什么结果 ， 你就可以把马上把这个一一对应的这个关系列出来 。

**吴涛** [2:30:55]
对 ， 呃 ， 所以这也就为我们提供了另外一个拥抱函数编程的理由 。

**Rio** [2:31:02]
理由 。

**吴涛** [2:31:02]
就是对 ， 没错 ， 呃 。

**Rio** [2:31:05]
测试好写 。

**吴涛** [2:31:06]
没错 ， 测试好写 ， 所以如果你们还没有接触函数编程的话一定要去试一试 。

**Rio** [2:31:12]
嗯哼 。

**吴涛** [2:31:13]
嗯 ， 对 ， 找机构对找工作很有帮助哦 。

**Rio** [2:31:18]
可以瞬间提升那个什么来着 ， 逼格 ， 打引号 。

**吴涛** [2:31:22]
提升内力吧 ， 应该是这个逼格不逼格何必呢 ？ 写测试有什么逼格 ？

**Rio** [2:31:30]
哈哈哈 ， 说的也是 。

**吴涛** [2:31:33]
对 ， 真的猛试只用 printf 来来来来验证自己的 。

**Rio** [2:31:40]
所以现在只用 printf 吗 ？ 哦 ， 我我我我我其实还是要解释一下， 我我之前写 Go 的时候其实也已经有在用这个在写测试了 ，因为 Go 它是随这个语言它就自带一个比较好的统一的规范 ， 就不用不用单独再学一个第三方的东西嘛 。

**吴涛** [2:32:01]
嗯哼 。

**Rio** [2:32:01]
就其实写测试 ， 特别写单元测试的话还是挺方便的 ， 这个是要承认一下 ，有时候还有点用 。

**吴涛** [2:32:08]
可能现在语言是一个思潮也是要越来越多的在语言内部集成一些 ， 比如说测试呀 ， 比如说调试呀之类的特性 。

**Rio** [2:32:18]
嗯哼 ， 对 ， 没错 。

**吴涛** [2:32:22]
OK， 那好吧 ， 今天就到这吧 。 您刚刚收听的是 IPN Podcast 网络旗下的 IT 技术主题娱乐节目 《 内核恐慌 》。IPN 旗下的其他六档 Podcast 包括 SoftCore 技术主题节目 《 非娱乐技术主题节目 IT 公论 》、 医疗主题节目 《 太医来了 》、 美食主题节目 《 未知道 》、 艺术主题节目 《 流行通信 》、 无主题节目 《 无次元 》、 故事主题节目 《Hi Story》 以及影像主题节目 《 影像 》。

### 结尾

**吴涛** [2:32:48]
啊 ， 如果你喜欢我们的节目 ， 欢迎为欢迎你为我们的节目捐款 ， 啊 ， 捐款地址是你可以把本节目再听一遍 ， 开头有讲 。

**Rio** [2:32:59]
我这个要念 ， 这个要念 ，是 colonelpanic.fm/donate。

**吴涛** [2:33:04]
对 。

**Rio** [2:33:04]
D-O-N-A-T-E。

**吴涛** [2:33:06]
好吧 ， 呃 ， 要提醒大家一点是不要加 https 这个这个网址 。

**Rio** [2:33:13]
反正它会跳转的无所谓 。

**吴涛** [2:33:15]
对 ，但是为了保证您的安全 ， 它会自动跳转到一个 ， 啊 ， 带 https 加密 ， 哎 ， 带 https 加密网站 。OK。

**Rio** [2:33:26]
今天的节目就到这里了 。

**吴涛** [2:33:30]
1.79GB。

---

本节目库由 PodHood（https://podhood.com）提供支持——播客网站平台。
