Archive for 2010年6月

永远的页

2010/06/15

最近看到有人质疑在今天的电子设备上阅读是否还需要保留『页』这个概念。他们认为『页』是印刷品时代的产物,在电子出版时代除了怀旧没有任何意义,电子出版物已经有了『页』的完美替代品:竖直滚动条。

对我来说,竖直滚动条平滑移动功能的直接后果之一是,在阅读的时候,你会情不自禁地试图避免阅读窗口(或者设备屏幕)边缘处的文字 —— 确实,它们太边缘了,因为没有页只有滚动条的内容没有上下留白,而对这种缺乏留白的逃避会延伸到你正在阅读的那四五行以外的一切文字,从而会无时无刻不让你希望把自己正在看的句子调整到窗口(屏幕)的正中间。于是窗口(屏幕)的大小失去了意义,读者的视界实际上被压窄到四五行。阅读的动作成了以句子为频度的『读 —— 滚动 —— 读』(甚至不是有阅读器还发明了自动卷动功能么)。竖直滚动条成了一个分散注意力的障碍而非方便的阅读工具。更糟糕的是,有了滚动条,文章的编辑者更难把握读者会看到什么样的页面布局,所以很多时候他们也就放弃了这样的思考。结果就是我经常在阅读的时候实在搞不好把一幅插图放到窗口的什么位置最协调(通常我发现最好的位置是赶紧把这个图片滚出窗口)。这实在是比『页』糟糕很多的阅读体验。

我很欣赏 Kindle for Mac 的做法:根据当前窗口大小把窗口的内容区域作为一页,不提供竖直滚动条,只提供翻页操作。因为没有滚动条,这是让我分心最少的一款阅读器。同时根据窗口大小动态的定义页的大小,也避免了在电子设备上照搬印刷品布局的古怪体验。我猜想在 iPad 和 iPhone 上的 Kindle 和 iBooks 也是类似的操作,因为没有窗口分割,所以页面的大小能更简单的固定为设备屏幕的大小 —— 但是 Kindle 没有进入 China App Store 所以我没有用过其 iPhone 版,也没有机会深入使用 iPad。

回顾一下,其实『页』这个概念还真的不一定就是印刷品时代仅仅因为技术局限而留下的遗产。古代人类不就使用过所谓的『卷轴』么?倘若假以改进,『卷轴』印刷品的便携性和不考虑到阅读注意力的单纯操作性不一定就输给『页』。所以我想,在印刷品时代,『页』并不是没有竞争者的无奈选择,而是在选择中胜出的更优秀方案。到了电子出版时代,人类历史依然会不断掀开新的一页。

Dict Mac 的发音功能

2010/06/08

对于词典软件来说,发音是个必需具备的基本功能,而且 dict.cn 的 Web API 提供了 MP3 格式的单词(短语)发音,所以从开始写 Dict Mac 的起,发音就被列入计划加入的功能。0.02 版完成之后,也就是从 5 月 25 日左右开始准备实现发音功能。

最初的问题是找到合适的 API,花了一个晚上,从 blog 和论坛的帖子堆里发现无数名称,逐一在 Apple 的文档里查找印证,最后终于锁定 Audio Queue Service 这个 framework。有了 framework 的确切名称后就不必再流连于 Stackoverflow 之类的网站,开始专心阅读 Apple 的文档。

花了一个晚上草草看了一下《Audio Queue Service Programming Guide》,感觉不是很好。这个 framework 功能比较强大,设计得比较灵活,相对来说也就没有提供傻瓜化的播放 API,即使是播放一个 MP3 文件也要 400 多行代码。好在这些代码在 programming guide 里都已经直接给出。但是一来我不喜欢这种 copy/paste 代码的方式,二来如果这些代码有 bug(当然 programming guide 里的代码本身有 bug 的可能性不大,但是和 Dict Mac 的 code base 集成的时候很可能引入问题),也要花不少时间解决,而且很可能要重读 programming guide 甚至查阅 API reference。

另外的问题是选择把 dict.cn 的 MP3 文件 download 到本地文件系统之后再打开文件播放的方式,还是直接播放网络的流数据的方式。从尽量减小暴露给用户的复杂度的角度说,稍稍倾向后者。但是考虑到今后还要实现本地缓存,以及尽早实现功能,还是决定先写出把 MP3 文件按照单词作为索引存储在本地文件系统的代码。花了两个晚上写好了这些代码后,第二天白天我脑子里突然冒出一个问题:OS X 会不会有现成的播放 MP3 的命令行工具?从以往的经验看,OS X 的命令行工具还是相当强大的。Google 了一下,果然有一个 afplay。这样一下子把实现发音功能的剩余工作从至少两个晚上变成了一个小时 —— 只要 fork 一个新进程运行 afplay 即可。

其实刚开始写 Dict Mac 的时候就考虑过是不是把必要的 UI 之外的其它功能都做成一个后端独立进程。最后决定当前阶段还是写成一个进程。不过 afplay 至少让发音功能成为了一个独立的进程。一开始我还在抱怨为什么 Mac OS X 不能直接提供一个播放 MP3 的傻瓜接口,其实这样的傻瓜功能应该做成工具而不是 API,像 Audio Queue Service 那样灵活的接口才值得作为 API 的形式提供。这个事情上 OS X 继承了 UNIX 的精髓,也是像 Windows 这样的不管底层功能还是傻瓜功能一股脑的做成 API 的非 UNIX 类的 OS 最缺乏的文化。