首页 > 代码库 > 一点小感受:界面和程序的分离
一点小感受:界面和程序的分离
1 Windows桌面程序,界面和程序是源码级混合
Windows系统下的GUI程序,界面(GUI)与程序其他部分逻辑上是分离的,但是源码上直接交互,界面功能直接通过调用Win32 API来实现。
例:CreateWindow()。
写Windows桌面程序,必须调用GUI32.dll导出的API,无他可选。
甚至线程模型很多功能都和GUI窗口绑定到了一起,如消息队列。
2 Linux程序,界面和程序是通过协议通信
2.1 CUI程序和文本终端通过终端协议交互
对于CUI的程序来说,文本终端是通过标准的终端协议(行行程协议)来提供接口功能的。文本终端和主机完全可以运行在不同架构的机器上,只要彼此都遵守同样的终端通信协议,程序和终端就能完美交互,而不受通信媒介的限制。
正因为如此,才使得SSH等远程终端等方便的远程连接方式很容易被理解和实现。
这种彻底的分离,带来了设计上的完美感。
让每一个程序员都去了解使用终端协议是非常费时(个人认为非常有意义)的事情,而且更可怕的是终端协议并不是只有一个,各终端设备厂家有自己的协议扩展,如VT100。
为了便于使用,人们开发了封装终端协议的函数库。最基本的就是C标准函数库里的printf(),scanf()了。功能更强大的就是著名的curses库了。当我们编写Linux程序使用这些库函数的时候,最好能想到其底下支撑它的终端协议。
2.2 GUI程序和XWindow Server通过X协议交互
与文本终端的概念一脉相承,XWindow提供了图形终端的功能。程序通过标准的X协议与图形终端XWindow Server交互。
图形终端的功能要比文本终端强大的多,也复杂很多,其通信数据量更是大幅增加。这些都导致了X协议的复杂性。所以直接通过X协议来调用GUI功能,显然过于繁琐。于是,人们开发出了封装X协议的XLib库,为了更加简单的使用,基于XLib库有开发出了各种高级封装库,如GTK,Qt等。
当我们使用这些库函数的时候,别忘了其底层最终是使用X协议与图形终端进行了通信。
2.3 直接操作的显卡不是终端
Linux支持直接操作显卡设备,特别是对framebuffer的支持使得直接读写显卡非常方便。然而这样的读写与界面的操作是两个完全不同的概念。Linux程序的界面就是终端,至于终端如何利用显卡那是终端的具体实现,对Linux程序不可见。就算是最简单的printf(),Linux程序也是写到终端上去,而不是直接写到显卡上。对于本地终端来说,终端和程序运行于同一台机器上,很容易让人混淆终端和显卡设备。要记住,本地终端只是终端中特殊的一种,理解终端概念的时候,最好想象远程终端的情形。
3 Web程序,界面(HTML)和后端程序通过标准HTTP协议进行通信
虽然Web程序也是图形界面程序,但是其后端程序对界面的控制粒度很大,而且程序不能主动发起到界面的通信,这些限制导致HTTP协议非常简单,通信数据量也很小。
越简单的事情往往越容易取得成功,Web程序最终取得了辉煌,成为了程序模型的主流,越来越多的桌面程序被同功能的Web版本程序取代。
当然了,由于Web后端程序对界面的操作功能有限,所以大量的图形图像程序不会被Web取代。
4 分离还是混合?
界面和程序逻辑是分离好,还是混合好?逻辑上,界面功能算是一个非常成熟独立的模块,从模块化设计的角度来说,分离是最完美的选择。然而,对于图形密集型程序和频繁交互的程序(比如Photoshop,3D Max)来说,界面功能占据了程序逻辑的大部分,此时交互的流畅性就成为关键。界面分离的程序交互效率必然受到影响,所以Windows和Mac的图形界面交互流畅度要大大高于XWindow。
然而毕竟图形密集和交互密集型程序只占据软件市场的很小一部分,对于广大的其他类型程序来说,界面的分离无疑会带来设计上的美感和简洁,运行上的稳定。看看大多数的服务器、嵌入式设备吧。
再者,硬件技术的提升往往比软件设计的改良更加容易,所以随着硬件水平的提高,界面的分离必将是最终的胜利者。
5 协议还是API?
程序不同模块的交互方式按照耦合程度由高到底可以分为:(1)源代码级别混合;(2)API函数;(3)协议。
源代码级别混合指的是彼此暴露数据结构实现细节,除非是非常简单的程序,否则这种设计基本是不合适的;
API函数级别,指的是把一个模块当成库来设计,对外之暴露有限的函数,使用透明数据结构指针作为函数参数,所有模块必须运行与同一个机器,同一个进程。
协议级别,指的是对外暴露通信标准,模块间通过标准的协议来交互。此时,不同模块可以运行于不同机器。
在(2)和(3)之间还有一个多进程程序设计的方式,各个模块被当作独立的进程来运行,模块之间通过本机IPC进行通信。
程序设计时,要根据程序的规模,具体的业务逻辑、扩展需求来确定模块间交互的方式。
一点小感受:界面和程序的分离