界面开发的三层境界

关键词:GUI框架,UI编辑器,界面引擎,MVC
作者:码匠信龙

第一层境界:代码写死
笔者大学时候开始学习的语言是C/C++,学习完基本的概念后,后面想开发有界面的应用程序接触的是win32,你会发现创建一个窗口或者一个button控件要写好多代码,例如配置标题,位置,大小,背景颜色,icon等等各种属性,api接口一大堆参数。

win32创建窗口api
HWND CreateWindow(
LPCTSTR lpClassName, //窗口类型名称
LPCTSTR lpWindowName, //窗口名称
DWORD dwStyle, //窗口类型
int x, //窗口的左上角X坐边
int y, //窗口的左上角X坐边
int nWidth, //窗口的宽度
int nHeight, //窗口的高度
HWND hWndParent, //父窗口句柄
HMENU hMenu, //窗口菜单句柄
HANDLE hInstance, //应用程序的实例句柄
LPVOID lpParam //创建的参数,一般为NULL);

创建一个窗口的伪代码

HWND   hWnd = CreateWindow( lpClassName, "我是个窗口",
        WS_OVERLAPPEDWINDOW,  0, 0, 500, 300,  NULL,NULL, hInstance, NULL );

创建一个按钮的伪代码

 HWND hButton = CreateWindow(L"Button", L"我是个按钮!", 
                          WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,  
                          35, 45, 160, 65, hwnd, NULL, hg_app, NULL);  

在这个阶段你会发现开发的界面不但巨丑,而且好像有看不完的api和各种奇怪的参数,生怕设置错了参数导致程序崩溃。例如最简单的要改变一个按钮或者图片显示的位置,你要不断的设置位置坐标直到满意为止,改变一次就要重新编译一次运行看看,这个过程非常繁琐耗时。

第二层境界:自动生成代码
用第一阶段的方式来开发复杂些的应用界面,你会发现效率很低。因为当你在创建控件,写好那些配置参数的那一刻就把代码写死了,后面要重新调整界面或者大改界面时候,很多代码要重新写过。如果代码是自己写的还好,如果接手项目的新同事要读懂到修改则是个痛苦的过程。工作后才发现有一种叫ui编辑器的东西,有点规模的公司一般都会有自己开发的ui编辑器,由1-2个人来开发维护。ui编辑器就是个界面的配置系统,大多数都使用结构化的配置文件来保存界面配置信息,如xml格式。像andorid,ios原生开发环境自带的界面开发都有ui编辑器,qt,unity3d,cocos2d-x这些都也有。

例如qt的界面ui编辑器
qt的ui编辑器

显示界面,只要ui解析器加载一个xml配置文件就可以,不需要写一堆配置控件属性的代码,ui解析器会根据xml配置文件自动生成类似第一层境界的代码,类似伪代码如下:

ui_parser.load("xxx_view.xml")

在这个阶段你会发现客户端ui界面开发瞬间变得轻松很多,界面的控件和参数在ui编辑器里配置好,程序里加载一下ui的配置文件,甚至一行代码都不用写,界面就出来了。如果boss不满意界面,使用ui编辑器修改轻松很多,不需要改很多代码。
细心的读者会发现,这不就是MVC三层模式里的界面View和逻辑代码(Model,Controller)分离的过程吗。是的,界面的显示和逻辑代码不再耦合在一起了,这样我们会更加专注于写逻辑代码。

在第二层境界,大部分有经验的程序猿可以相对轻松的开发界面了。但是真正商业级的产品会给你提无数乱七八糟的需求,而这变化的需求不是一个通用控件可以搞定的,你会发现用xml配置那些写好的控件,到底还是太麻烦或满足不了你的需求。例如策划想游戏里面活动相关的按钮周围有酷炫的动画显示或者粒子效果,吸引玩家的注意力,或者这个按钮有可以按照某个轨迹移动的属性等等。

带闪光效果的按钮

这时候,你可能会为了快速完成工作任务,新建一个XXX_Button类,继承原有的button基类或者直接修改button控件基类,添加新的动画属性、粒子效果属性,移动属性,然后ui编辑器添加相应配置的属性。下次有新的需求,再类似这样修改。如果不只是button控件要添加这些属性,策划还想下拉框、单选框、列表、文本等控件,也有各种需求,原有的控件不能满足,而有些控件添加相同的属性,这时候该怎么办呢?

如果你使用的这个ui编辑器和ui解析器不是开源的,例如android,ios原生开发工具,qt designer等,当原有的控件不能再满足策划的需求,通过继承原有控件基类或自己重新自定义新的控件类型方式开发,这时候闭源的ui编辑器不能自适应新的控件类型,你又会倒退回第一层境界的方式来开发gui,开发效率又变低了。

第三层境界:抽象的层次和组合
在第二层境界,笔者也想了好久,怎样的ui框架或者ui编辑器可以适应各种需求变化,更方便开发,参考了其他各种ui框架和ui编辑器。

最终发现,当你的思维观念中还执着于传统的ui控件体系,还执着于ui框架和ui编辑器的时候,很难再往上提高,需要有勇气去打破原有的思维观念,这对其他编程概念也是一样

后来笔者在迅雷bolt的界面引擎和html+css+js找到新的思路,不是一上来就用传统的控件体系开发界面,而是把控件共同的属性抽象成更小粒度的元素,比控件层更高一层次抽象,例如迅雷的各种原子控件或者html里各种的基础元素,通过不能再拆分最小元素自由组合拼装成更适合你的控件。你会发现web前端总是不断有各种酷炫新的ui框架出来,开发界面速度比客户端用原生的开发工具要快, 是因为这种模式更容易定制你想要的ui控件。慢慢你开始定制自己的UI框架,而不是使用别人开发的。再配合脚本语言(如js,lua)的粘合,ui编辑器里也可以轻易编写控件的交互逻辑,不单单只是配置控件属性。

如qt里的qml语法格式非常像CSS,但又支持javascript形式的编程控制。

unity3d的组件方式也是用这种元素+组合的方式,但它是把一切都抽象成object, 提供各种组件,你需要什么功能在object上添加组件就好,例如添加个label组件就变成文本控件。

第二层境界扩展控件方式
继承方式扩展button控件

第三层境界编写控件方式
小粒度元素组合方式的button

读者再来看个html、css、jq制作的一个简洁的音乐播放器的例子

界面例子.png
你会发现用html和css代码很少,却很容易做出简单酷炫的界面,同时css的代码可以被复用。

界面开发是个很广大领域,有很多相关的概念没有涉及到,笔者写这篇文章也算是对过往开发的一个经验总结吧。

版权声明:本文为博主原创,欢迎转载分享,只需注明作者与出处http://thinkingroom.me

原文地址:https://www.cnblogs.com/thinkroom/p/6708794.html