桌面程序的完整架构体系
对于桌面程序, 最核心的话题是交互. 为了把关注点收敛到交互上, 我们下面主要讨论, 交互范式的设计
从需求角度看, 桌面程序的交互方式并不稳定, 它的交互范式经历了很多次的变更
命令行交互
最早出现的交互范式是命令行交互程序. 使用的设备为 键盘+显示器
输入被抽象为一段以回车(Enter)为结束的文本, (如果是多行文本,在行末输入 “\”对回车进行转义)
输入方式有二: 一是命令行, 二是标准输入(stdin). 输出也是文本, 但是输出目标有可能是标准输出(stdout), 也可能是标准错误(stderr).
正常情况下, 标准输出(stdout)和标准错误(stderr)都是向屏幕输出. 这种情况下, 肉眼并不能区分输出的内容是标准输出,还是标准错误
命令行交互程序的输入输出可以被重定向. 一个程序的输出, 可以被重定向写入到文件(标准输出和标准错误可以输出到不同的文件以进行区分), 也可以通过管道功能重定向为另一个程序的输入.
命令行交互程序的结构可示意如下:
命令行程序的限制过大了, 很多需求场景下都很难做好, 比如编辑器.
字符界面(比如 vi)
于是, 字符界面程序出现了. 使用的交互设备仍然是键盘 + 显示器 但是输入不再是一段文本, 而是键盘按键事件 (KeyDown和KeyUp).
输出也不是一段文本, 而是可以修改屏幕屏幕任何位置显示的字符 (屏幕被分割成M*N的格子, 每个格子可以显示一个字符).
这个时候, 键盘的功用在需求上分化为两个: 一是输入文本, 二是输入命令(通常通过扩展键比如方向键, 或者组合键 比如 Ctrl-A, Alt-X). 从输入文本的角度, 需要有当前输入的光标(Caret) 位置.
字符界面程序保留命令行输入的方式, 但一般不太实用标准输入
上图的TDI是 字符设备接口(Text Device Interface), 它指的是一组向屏幕绘制文本的方法集合. 大体看起来是这样的:
func ClearScreen()
func DrawText(x, y int, text string)
...
字符界面程序也有很大的局限性. 最典型的需求场景是游戏. 字符界面对游戏场景能够做的事情非常有限.
图形界面
于是乎, 图形界面出现了. 使用的交互设备是 键盘 + 鼠标 + 显示器 + 音响
从交互演进的角度,这是一个划时代的变化
与字符界面时期相比, 图形界面时代变化的根源是输出的变化: 从字符变成像素. 屏幕被分割为精度更高的M *N的格子, 每个格子显示的是一个很小很小的像素, 每个像素可以有不同的颜色.
为什么会出现鼠标? 因为屏幕精度太高, 用键盘的方向键改变当前位置不只是看起来非常笨拙, 而且操作上也很不自然
为什么会出现音箱? 它是声音设备演进的自然结果, 在字符交互时期就有声音设备了, 计算机主板上有内置的喇叭.
喇叭的用途是出现重大错误时会响几声给予提示
与字符界面程序相比, 图形界面程序还有一个重大变化, 是多窗口(部分字符串界面也是 比如 Turbo C++ 3.0
窗口(Window), 也有人会把它叫视图(View), 是一个独立可复用的界面元素. 复杂的窗口可以切分出多个逻辑独立的子窗口, 以降低单个窗口的程序复杂性.
窗口有了父子和兄弟关系, 就有窗口系统. 一旦界面涉及复杂的窗口系统, 交互变得更为复杂. 例如: 键盘和鼠标事件的目标窗口的确定, 需要一系列复杂的逻辑
为了降低编程的负担, 窗口系统往往接管了桌面程序的主逻辑, 提供了一套基于事件驱动的编程框架, 业务代码由窗口系统提供的界面框架驱动. 整个程序的结构如下所示
GDI 图形设备接口(Graphic Device Interface) 它指的是一组向指定窗口(注意不是屏幕) 绘制图形的方法集合. 绘制的对象包括有 几何图形, 图像, 文本等
此后, 到了移动时代, 手机成了最主流的计算机. 使用的交互设备发生了变化, 变为 触摸屏 + 麦克风 + 内置扬声器
鼠标交互的方式变为了 多点触摸
鼠标 + 键盘 + 显示器
的能力被融合到触摸屏上
音响也被内置到手机中, 变成内置扬声器. 这些变化都因移动设备的便携性的诉求引起. 从架构角度, 它们没有引起实质性的变化, 只是鼠标事件变成了触摸事件
智能交互
麦克风让计算机多了一个输入: 语音. 有三种典型用法
一是在应用内把语音录下来, 直接作为类似照片视频的媒体消息, 或者识别为文本应用
二是作为语音输入法输入文本( 可以认为是第一种的特例)
三是基于类似 小爱同学 语音助手来交互
语音助手是被寄予厚望的新的交互范式. 它可能开启了新的交互时代, 我们不妨把它叫智能交互时代. 但当前它与图形界面程序结构并不相容, 而是完全自成体系
为什么语音交互和图形界面没法很好的融合在一起?
- 语音交互有很强的上下文, 所以语音交互程序通常其业务代码也由语音交互系统提供的框架驱动. 框架的特点是侵入性强, 框架与框架之间很难融合
- 语音交互还不成熟, 所以独立发展更简单, 如果有一天成熟了, 完全可以重写框架, 把语音和触摸结合起来, 形成全信的交互范式