大家还记得电影《阿凡达》中的女主角——潘多拉星球的佐伊·索尔达娜吗?她将辫子和坐骑相连,以此来控制坐骑的飞翔。这想来是多么奇妙的一件事啊!本文要介绍的主角是软件开发领域的佐伊·索尔达娜——一个可视化编程的开发平台“Tersus”,一款来自以色列的软件。这款软件的神奇之处在于不用写一句代码,只需要画图,这个图就会在执行引擎的支持下运行起来。
Tersus平台介绍
关于Tersus的官方介绍这里就不多说了,感兴趣的可以访问Tersus的官网了解(www.tersus.com),本文的内容只是介绍使用Tersus的开发方式,以及和常规开发的对比,这里使用的例子非常简单,关于Tersus的内容非常多,本文这是抛砖引玉,更多的内容,如果大家需要我会继续介绍。
Tersus确实有别于常规的快速开发平台,它不是一种语言,而是一个环境,基于Java。主要包括如下几个核心部分:
- 一个组件化的开发环境:它的开发环境基于Eclipse,使用Eclipse的开发者可以很容易上手,这个开发环境还包括运行和调试环境;
- 一个解析引擎:用于解析运行我们通过“堆积木”方式搭建的系统,这个系统基于系统提供的大量的组件(系统中称为模板(template),为了便于理解这里使用组件),如果你愿意可以实现自己的自定义组件,实现的,因此部署的时候这个引擎也需要随产品发布,类似于.net framework,属于一个支撑环境;
- 非常多的基础组件:例如数据库的插入、更新、查询等等都以组件的形式出现,要使用只需要拖到工作区,使用平台中称作Flow的组件和对应的数据连接即可,这里的Flow可以理解为数据流,本质上代表数据的流向。
一个例子
我们通过使用Tersus开发一个简单的用户管理系统进行介绍,功能非常简单,如下图,包括一个用户列表,这个用户列表必需登录才能看到,业务很简单吧,但已经可以管中窥豹。
开发模式介绍
知道了平台的核心组成,下面就聊聊使用它开发系统的一般步骤,这里的步骤是个人使用经验总结,可能不同于官方教程。
由于平台的开发环境基于Eclipse,因此会比较容易上手。
篇幅关系,我们这里主要介绍使用Tersus平台开发的登录模块,虽然Tersus本身带的模板组件中有提供带有权限验证的整体模块,但我们还是自己动手来实现下,毕竟登录的步骤、过程都是大家非常熟悉了的。介绍的方式呢,我们先总结使用Tersus平台开发的一般步骤,然后再按照这个步骤,从零开始来实现用户登录的验证和授权的过程。
一般步骤如下:
- 新建一个Tersus Project的工程,选择对应的模板和主题;
- 如果选择了空白主题,就需要自己来提供项目所使用的界面资源,如html、css、js等等,推荐使用Legacy Navigation模板;
- 在主工作区绘制代表视图的容器组件,可以是最顶级的View,也可以是Pane或者Variable Pane;
- 双击要编辑的视图组件,在其中加入其他的组件,比如按钮、文本框、下拉框等等;
- 对于按钮这样的有事件处理机制的元素,就继续双击放大该组件,在其中加入事件处理模块如Action或Service,需要处理客户端数据的只能用Action,Service只能处理服务端的数据;
- 为平台通过的组件,或者你自己添加的处理模块如Action、Service添加必要的Slot,这个Slot我的个人理解就是相当于电源插座,或者网线接口,或者干脆你可以理解为阿凡达中那些人的辫子,可以通过flow连线将这些slot连接起来,但要注意连线两端的slot类型需要匹配;
- 基本操作就这些,开发一个应用,基本就是上述步骤的重复和组合。
让我们开始吧 Let’s Rock!
- 新建一个Tersus Project,选择Legacy Navigation,Theme选默认好啦,如图:
- 点击完成,新项目就建立了,此时的仓库浏览器和主工作区显示如下:
- 至此为止,我们没有写一行代码,但已经可以运行了,可以看看效果:
可以看到已经有界面了,这个初始的界面就是在第一步咱们选的Legacy Navigation模板,仔细点观察发现左下角有个Javascript脚本错误,原因是没有任何视图可用,Tersus框架在取视图数据时遇到空值产生的,如下: - 现在我们加入一个Pane视图,作为页面元素的容器,并将该视图命名为:“登录”,这里顺便提一下,你可以在任何时候按F2为元素命名,这个命名很重要,在某些元素上,名称直接参与了模型解析,例如可以为Database-Find组件增加一个Trigger(触发器),该组件自动生成的Sql语句中,会使用这个触发器的名称作为过滤条件,其他还有很多,例如表示在鼠标点击时才触发。
- 接下来,就是向登录视图中添加组件了,为了逻辑简单,我们的目标是设计这样一个界面,在登录前显示“登录”超链接,登录成功后登录超链接消失,代之以“注销”超链接,并且在下方显式一个当前用户的列表,这个用户列表也是读取自数据库,在后面的介绍中会涉及数据的读取以及在前台表格的显示。如:
为了放置登录按钮,我们先在Pane里放置一个用于控制水平位置的组件:Display-Row,并将之命名为:“链接”。并在Row组件中放置一个Variable Pane和一个Action,前者放置登录前后两种状态下的文本信息:登录链接和注销链接,后者负责根据用户是否登录系统选择显示登录前还是登录后的信息内容,要编辑某一个组件,可以随时双击鼠标,这样目标组件就会自动放大到最大以方便我们编辑双击Row组件,向其中加入Variable Pane,双击Variable Pane扩大后,向其中继续加入两个Pane组件,分别命名为:登录前和登录后,并在其中分别加入两个Display-Label组件,其中组件的链接是通过在Label组件中加入名为“”的Action实现的。这两个Pane组件中还要各加入一个DataTypes-Boolean组件,并命名为“”,用以控制Pane的显示状态为隐藏还是显示。如下图: - 接下来,为登录按钮添加处理逻辑,双击登录Label中的Action,将之放大,向其中添加Display-Dialog对话框组件,这是一个基于Div的模式对话框,类似于Windows7关机时的效果。和添加前面的Vaiable pane类似,这里也要添加一个协助布局的组件:Display-Grid,并在其中加入两个Row,分别是:用户名行和用户密码行,这两个Row中分别是:“用户名(Label组件):文本框(Text Display组件)”和“用户密码(Label组件):密码框(Password Input Field组件)”
- 要看到运行效果,要首先为之前的“条件显示”Action添加控制逻辑,它根据用户是否登录来显示“登录前”还是“登录后”的内容,如下:
条件显示Action中包括两个Action:“是否已登录”和“显示登录后的内容”,其中的主要逻辑是:前者检查用户是否登录,后者检查结果显示登录后的内容,如果用户未登录,则将登陆前管显示的变量()设置为Yes——即显示登录链接。其中“是否已登录”Action根据检查的结果返回true,或者false,相对常规的开发,这里的返回值已经被可视化为了两个slot,就是上图中的“未登陆”和“已登录”,如下:
Tersus平台的这种特点使得平时中的方法、参数可视化为了Action和Slot,如果要改变参数,或者方法的内容,只需重新绘图即可。另外,我们可以看到,这样一个Action是可以复用的,我们可以在任何其他需要相同逻辑的地方复用它,就像复用一个对象,或者方法。
接下来,咱们再看看“显示登录后的内容”Action,先看图再解释,如下:
这里使用了一个Collections-Create组件来创建前面绘制的登录后的内容Pane,请注意位于图上方的触发器和右方的Exit Slot,它们在这里类似于无参数的方法调用,提供了相同的效果,关于这些Slot的应用,个人认为是个难点,请大家注意观察和思考。
其中有一处需要指出的就是Yes到登陆前的变量的传递,如图:
这里要表达的意思呢,就是在登录未成功后,将Yes值赋给变量,这种传值方法要学会,其实也很简单啦,相当于在一个if的条件判断语句中,根据表达式的结果为变量赋值,就这点事。 - 现在,终于可以看到界面了,先运行试试看,这里插一句,使用Tersus平台的一个方便之处就是,因为它是“模型-解析”机制,因此我们在修改模型后不需要重启应用服务器,而且刷新的速度非常快,因为模型是已xml的形式存放的,并不涉及类的rebuild,虽然在常规开发中也不需要重启服务器,但因为涉及到类的rebuild,还是会造成时间的拖延,具体的时间有长有短,和机器的配置也有很大关系,从实际的运行情况来看,Tersus的运行效率还是很不错的,因为我的平台环境构建于VMWare虚拟机中,运行速度还是非常的快,07年的老本子,难得了。
点击“登录”链接后弹出窗口如下图所示。 - 这个时候点击OK按钮还是没有作用,但Cancel按钮是有用的。原因很简单,我们还没有给OK按钮添加逻辑处理功能。还有一点,可能有的朋友会问,这两个按钮哪来的?我怎么没看到呀!答案就在于类似弹出窗口的组件都有一个共同的部分:
双击Footer就可以看到那两个按钮啦:
是不是节省了做界面的时间和工作量?还有一点就是包括我自己,都有这样的苦恼,就是做的多个软件产品,界面的风格不够一致,相信其他朋友也有类似的苦恼,这个问题在某些时候确实不是问题,但当软件的规模达到一定程度,界面的风格不统一或者说操作的不一致性带来的问题就比较严重了。
同样地,双击OK添加控制逻辑,或者根据自己想需求,为这两个按钮重新命名。 - 现在,我们为OK按钮添加控制逻辑,这个逻辑是这样的:
1、系统预先准备了一个默认的管理员帐户(用户名:admin,密码:admin);
2、用户输入用户名和密码并点击OK按钮以后,系统会接收到这两个值,并在数据库查询,查看是否匹配,以决定是否允许用户登录;
3、用户登录成功以后,系统将用户的UserID加入会话中,并弹出消息框,提示用户登录成功,并刷新当前页面;
4、用户登录失败后,系统提示失败,并让用户再次登录; - 下面,我们看看使用Tersus如何来实现,这里只是用户验证和授权,数据的准备我们会放在另一个Action中予以处理,这里暂且不谈。这里的逻辑位于OK按钮之中,因此双击放大OK按钮,在其中加入登录的控制逻辑,主要由四个部分组成:
1、登录窗体
2、登录服务,使用Service组件进行的封装;
3、关闭并刷新,使用Action组件进行的封装;
4、显示错误信息,使用Action组件进行的封装;
先来看看图是什么样的:
在这一层,用户登录窗体为登录服务提供了用户名和密码,登录服务有两个出口,成功则关闭窗口并刷新,失败则显示错误信息。接下来,就是进一步完成各个组件的内部逻辑。 - 首先来解析“登录服务”中的逻辑,同样双击放大它,在这个画布之上,你可以信马由缰,顺着你的思维来调兵遣将,此时你不需要过多的考虑技术问题,只需考虑业务如何表达即可。先上图,好解释些:
在这张看似简单的图中包含了如下几个操作:
1、将给定的用户名转换为小写形式
2、连接数据库,并从用户表查询User_ID为指定值的记录是否存在,如果存在则读取出该条记录
3、将查出记录中的密码字段值和给定值对比,一致的话呢就将用户设置到会话中
这里特别要说明的是User模型,它是一个数据库类型,Find组件通过User模型就可以执行在实际数据库的查询了,如果要这个查询增加一个条件的话,只需要给这个Find组件添加一个触发器,如上图中的User_ID。 - 好了,现在“万事俱备只欠东风”,这东风是什么呢?很显然是数据库中的数据,最起码得有个默认用户吧,不然我们怎么登录呢?接下来我们就做下这个初始化工作,这个工作由一个Service来完成,它和登录Pane平级,系统初始化时此Service会被首先执行,好吧,该它出场了,它的名字叫做“初始化管理用户”,如下图:
我们看看它究竟做了哪些初始化工作:
它主要做了三件事:
1、检查是否有默认用户,没有则插入一个默认用户,帐户和密码均为“tom”;
2、检查是否有默认角色,没有则插入一个默认角色:“Admins”,并给默认用户分配角色;
3、检查是否有默认权限,没有就初始化一个权限,并为默认角色赋权
这里我们以“检查是否有默认用户”和“插入默认用户”这两个Service为例,如下图:
第一个Service重用了之前建立的User模型,使用Find组件简单的实现了检查User表是否有数据的工作。
第二个Service插入一条新纪录,一个字符串常量和User数据模型的两个字段相连,没有赋值的字段系统将会自动赋值NULL,使用Insert组件将数据插入到数据库。
其他的Service基本雷同,这里就不再赘述了。 - 完成了这些工作,可以说已经完成了一大半,现在系统已经支持登录操作了,如下图:
可见,系统正确的执行了,只是此时我们还未给注销按钮提供任何执行逻辑,现在我们就添加这个退出行为处理程序,其简单到不可思议,只需在注销按钮的事件处理Action中添加Display Actions-Logout组件即可,如下图:
现在单击注销按钮系统就会退出到登录前的状态,它帮我们完成了登录信息的清理工作,一般需要从会话中删除当前用户的登录信息。 - 继续,我们添加一个数据列表,以显示当前用户表的记录信息,在“登录后”的Pane中添加另一个Pane,我们给他命名为“用户列表”,在这个Pane中添加一个Display-Simple Table组件,和一个负责为这个表格组件填充数据的Action,如下图:
注意左边的表格组件,里面我们放入了User模型,其实就是指定了要显示的目标数据源,因为要显示的多条数据,因此需要指定User模型的repetitive(可重复性)属性为true。在右边的Action中,首先我们使用一个Service封装了查询User模型数据的逻辑,然后将查询结果关联到了用户表。好了,大功告成,检验下成果:
总结
Tersus这个平台,用于快速开发还是非常不错的,初学者也可以使用,但并非有了Tersus就不需要学习编程知识了,数据库、算法、Java、Web编程知识同样需要,至少有了这些基础知识或者编程经验可以让你更好的使用Tersus。本文没有介绍到的内容还很多,比如部署、调试以及一些故障诊断及排查等等,我们会在后续的文章中向大家介绍。最后,我们使用一个表格作为结束,该表格对于Tersus和常规的开发模式做了比较,比较的项目还在持续增加中。
比较项目 | 使用Tersus | 常规开发 |
开发成本 | 较低。原因如下: 1、对于开发人员的要求降低了 2、开发人员的工作输出为一系列配置文件,避免了不同开发人员技术水平和积累不同带来的代码质量差异,并降低了产生BUG的风险; | 较高。原因如下: 1、对开发人员的技能要求较高,高技能意味着高薪酬; |
开发效率 | 较高。原因如下: 1、不涉及代码,完全基于图形的开发模式,鼠标的拖拉要快于coding代码 2、平台提供了许多组件可供使用,自己也可以封装扩展 3、遇到BUG可以使用非常灵活的调试方式,快速定位问题 4、系统提供了系统运行日志,可以快速定位问题根源 5、不需要考虑操作系统和浏览器差异,支持主流Windows和Linux系统,以及IE和Firefox | 不确定,因人而异,因团队而异。 |
可测试性 | 较方便,可以使用Test Runner进行自动化测试。 | 较方便,可以使用JUnit进行自动化测试。 |
部署 | 较复杂。部署在目标服务器前需要安装部署环境,这个部署环境所需工作较多,但幸运的是每台服务器只需做一次。 | 较方便,可以直接部署于Tomcat、Weblogic等应用服务器。 |
维护 | 较方便。技术支持人员可以录制系统运行脚本,开发人员可籍此快速重现定位问题根源。 | 较复杂,依赖于系统的日志系统粒度和系统开发的质量,差异较大。 |
============================================================================
转载请注明出处! 作者:姜晓东 博客:http://blog.csdn.net/abigfrog QQ:800736 MSN:j2ee@hotmail.com
============================================================================