6.第三阶段--体系化
本文中的术语界面元素,在一般的书籍中称为窗口组件,但是最近的SWT、GWT等都喜欢用Widget做类名,中文翻译和组件没什么关联,因此换个名称。 |
上一篇文章用一句话来概括,就是基于界面元素的权限系统的可实现性分析。界面元素指窗口、面板、控件等。
本文继续挖掘该对象模型的潜力。上文我为了对应旧代码,使用了脚本权限(ScriptRight)标签,这个标签太灵活了,让我们难以分析在特定上下文中的作用。
就好象一个人,啥都会做--俗称打杂,就很难发现专业特长。话说几年前我打杂的时候,有天正在招聘办公室扫地,有位仁兄飞一般的到来,把我刚扫好的纸片吹得到处都是,没办法,只好继续扫,顺便八卦的听着这段面试内容。
考官:都做过什么职业?
应聘人:做过寨主,养过马,当过私人保镖。
考官:......
考官:会驾驶交通工具吗?
应聘人:筋斗云,月光宝盒。
考官:......
考官:拿过什么职称?
应聘人:斗战胜佛。
考官:......
考官:你觉得你适合做什么工作?
应聘人:做什么都行。
考官:......
最后该仁兄没有被录取。所以说人哪,还是专业点好。(后来我继续发扬八卦精神,才知道是总经理听到他说当过寨主,而我们又是山寨企业,于是...)
咳咳,言归正传。
6.1简化配置--权限上下文环境
整理一下权限的类体系。
现在,上篇文章的权限可以这样写
<RoleRight id="普通员工权限" roleName="普通员工角色"/> <RoleRight id="经理权限" roleName="经理角色"/> |
而角色权限的matches方法的实现方式,就是根据roleName参数值和当前用户名select一下数据库就可以了(当然,可以用点模式来解耦,直接硬编码是不好地)。
可以看到,权限有了具体的上下文环境,比如上图的角色环境,或者工作流环境,还可以根据其他上下文环境创建更多的权限,我们再回想一下客户天天提的问题
客户:我希望只有在发起申请流程时能填写请假原因控件,其他步骤无论如何也不能修改它。(工作流应用场景) |
客户:我希望总经理办公室的人能够查看所有申请单的明细信息,但没有任何操作权限。(角色场景) |
是不是能立刻对应上呢。也就是说,这个设计可以快速的对用户的界面更改需求做出反应。这样开发人员可以摆脱界面需求变更的束缚,专心的处理业务逻辑。
6.2图形化开发--IDE
有了一套完全对象化的模型,估计大家也看得出来--可以用画图的方式进行开发!
现在假想一下一个简单的IDE,如下图,其中红色部分为解说。
另外,这图我画了好久...
6.3集成到已有框架--使用布局
大部分情况下,我们都不应该自己重写一套框架,原因自然是不要重新造轮子。
整篇文章都围绕着加入权限配置后的界面元素如何显示,概括起来,那就是:
l 界面元素级别的权限。
l 根据上述权限对所涉及到的界面元素动态排版。
现在我们从下图看看界面元素排版大概都有什么规律。
可以看出,一般界面大体上分为
l 业务信息区域--文本框,文本,下拉列表等,纵向排列,一行2个控件,第一个为标题(Label)。
l 命令区域--一堆提交按钮,横向排列。
当然,这种界面内不同区域内的元素拥有一定的排列规律早在很久很久以前就发现了,还有个名称布局(Layout)。据史料《设计模式》记载,ET++框架在1988年的时候就采用了Flyweight模式,将所有布局和绘制行为代理给一个单独的Layout对象。
时下流行称之为布局引擎(Layout Engine)。目前,流行的GUI框架中,SWT, Swing, wxWidgets(用了Sizer命名)都拥有布局引擎;但B/S框架方面就比较寒酸了,目前我只知道有GWT;javascript方面有ext-yui。所以扩展计划,推荐在这些框架上进行。
我就不重复已经存在的Flyweight模式和布局引擎的学习资料了,读者可自行放狗搜索,下面简单画出本文的简单架构图,作为结束。
下图中,界面容器类指窗口(Window),表单(Form),面板(Panel)等能够包含其他界面元素的类。
权限配置器即类似Hibernate的Configuration类的作用,从Hibernate.cfg.xml和多个*.hbm.xml中获取每个类对应的配置信息。
7.后记
在2004年,我已经基于此概念写出一套独立的GUI框架,并在数个项目中应用,但是因为水平的关系,没有今天各位所看到的文档这么简练,愚以为虽然概念很不错,但当时实现过程有很多反模式。
自从去年开始,苦练文档能力,时至今日,觉得自己的忽悠技术,终于上了一个台阶,老泪纵横,打造此文,以资交流。
另外,写此文的目的,也在试探大家对于这个技术的兴趣,从目前来看,反响还不错,看来适当的时候,可以考虑开源实现,如果对开源本文的技术有兴趣,请联系我的电邮cm4ever@163.com。
谢谢你阅读本文,你的关注,就是我的动力。
8.代码量数学分析 有网友质疑本文所描述的对象结构的代码量比其他编程方式多,俺只好用拙劣的数学知识,花了1个多小时把代码量对比写出来。
8.1 定义 权限集合为a(a1,a2,...,am),a1为一个具体的权限,以此类推。 受权限影响的界面元素集合为b(b1,b2,...,bn),b1为被a1影响的元素个数,以此类推。 权限总数为c=count(a) 界面元素集合为d(d1,d2,...,dn) 界面元素总数为e=count(d) 函数 f表示权限和受影响的元素的关系
传统界面编程常用两种方案: 8.2只有一个界面文件,所有界面逻辑都在该文件中。 这里算法稍微复杂,如果你曾经写过上千行内含无数if...else的界面逻辑程序,请耐住性子看看。
∩指交集,假设权限影响到的具体界面元素函数i为i(a1)=d1,d2,i(a2)=d2,d3 则权限a1和a2的交集为d2,元素d2的代码要多写一次,产生代码增量,因此函数f如下 f(m) = i(a1)∩(i(a2)+i(a3)+...+i(am)) + i(a2)∩(i(a3)+i(a4)+...+i(am))+...+ i(am-1)∩i(am)
此时元素+权限代码量为f(m) + e + c
这种情况,权限不多的时候代码量较少,但是还记得老板和客户总是不耐烦的说改个界面怎么花那么长时间,以及投过来质疑、鄙视的眼光?因为工作量就是这样出来的,现实就是依靠人肉分析权限交集然后硬编码,界面逻辑维护的梦魇就在这里,当权限增多的时候,交集大量增加,还记不记得那个上千行的界面程序文件?这种情况,需求根本跟不上变化,只有不停的编码。
最复杂的情况是所有权限影响的元素都有交集,即每个界面元素至少伴随着一个权限判断,此时是2倍代码, 此时f(n) = (b1+b2+...+bn)*2 此时元素+权限代码量为f(n)
8.3按照权限分开界面 简单情况即每个权限对应一个界面程序文件 则f(m)=c
那么元素+权限代码量为f(m) *(e + 1)
这种情况比上一种好,但只是把痛苦转移到了其他地方,看看代码量就知道了,呈指数级增长。界面权限是分开了,但是所有界面元素也就翻倍了,每个界面元素改变,每个文件就要改一次;每加1种权限,就复制出一个新文件然后修改。被改动的文件都得重新测试过。而且如果还有复杂的组合权限-即权限并集(&&或者And操作),还是得照8.2的方式写代码。
要是碰到有人把几个界面程序文件中共同部分抽取为几个模板,那就更好玩了。除了要应付组合权限,还要小心维护模板,因为会产生8.2所说的受影响交集,此时是不受权限影响元素+受权限影响元素+权限编码3者交集,简直就是反模式bug磁铁,比8.2好不到哪里去。
这种情况不要谈界面逻辑的可视化和文档化了,一段需求逻辑都分离成这么多文件了,还想要啥。
不过倒是有点代码复用的意思,怎么说也复制了几次...
8.4按照本文提供的方式 b则可以理解为权限引用的个数。 则f(n) = b1+b2+...+bn
那么元素+权限代码量为c + e + f(n)
代码量非常稳定,而且是线性增长,最重要的是,整体对象模型和可图形化配置--其实我觉得凭这点,就已经比其他编码方式优秀了。
|