OEA中的AutoUI重构(1) - Command自动生成

简介:

OEA框架的核心之一是AutoUI,其职责是面向领域模型及UI元模型进行生成统一的界面。

    在本次的迭代开发中,需要对命令按钮的生成方式进行一些定制。由于原来并没有为这样的需求留有特别的扩展点,加之原来的生成代码是过程式的代码、且也变得比较冗长,所以我们决定对这一部分的代码进行重构。


原来的模式

    历史代码中,为某一实体类生成命令按钮的流程是这样的:

  1. 找到实体类可用的所有命令按钮元数据。
  2. 对它们进行过滤,依靠权限、版本的客户化元信息等。
  3. 构造几个生成控件的List容器,分别是:itemsInToolbar,itemsInContextMenu,itemsInGroup。
  4. 遍历所有的命令按钮,根据其对应的元数据,分别生成相应的控件(按钮、菜单等),然后添加到容器中。
    其中,还有对某些命令的特殊生成处理。例如,为了给命令生成一个附带的文本框,特别添加了IParameterizedCommand接口,实现这个接口的命令,则会调用它自己的控件生成方法来生成控件。应用开发时,扩展的命令需要实现自己的控件生成方案。
  5. 对同一容器中的命令控件进行排序和一些其它的操作。
  6. 把容器中的每一项添加到界面中。

    由于功能是一点一点加进来的,整个代码是过程化的,冗长而不易维护。扩展起来也比较不便。原来只能实现IParameterizedCommand接口并自行生成文本控件,要在总体上控制整个生成流程也只能修改上面的流程中对应的代码,最终只会导致代码膨胀得无法维护。


草稿

    重构不是重做。所以我们不是全部推翻重做,而只是把流程进行优化,并进行职责划分,用适当的对象来承担对应的职责,让类与类之间的协作来完成整个流程。

    首先,整个流程中比较重要的是控件的生成和分组。在进行OO设计时,先要对这部分进行抽象。先看看原来的生成的ToolBar的一张图:

image

(样式没有做,不好看,哈哈。)图中,主要有三类:分组下拉、带文本的按钮、一般的按钮,当然还应该包含右键菜单中的菜单项。再加上这些迭代的新的样式,画出了下面的草稿:

image

图中,主要的GroupGenerator的职责是对一组命令进行控件生成,一般情况下一组命令可以生成SplitButtons、GroupTextbox。当一个组中只有一个命令时,它就变为了特殊的ItemGenerator,当个命令可以生成:文本按钮、一般按钮、菜单等。而如何把所有的命令进行分组并生成GroupGenerator,就是GroupingAlgorithm的职责。


详细设计

    (以下内容中涉及具体的OEA的类的职责,用于项目组内沟通,不关心的朋友可以直接跳过细节描述。)

    最后的具体设计方案中,分为以下几下主要的部分:

image 

  1. CommandAutoUIContext:这是对整个生成环境的抽象。
  2. CommandAutoUI:这里面包含了整个生成的流程。
  3. Generators:这里面包含了所有的框架内置的命令组生成方案。
  4. GroupAlgorithms:这里用于把命令进行分组,并为命令组分配生成器。

以下,详细说明每个部分的设计:

CommandAutoUIContext

image

CommandAutoUIContext 表示生成流程的上下文对象。它比较简单,只是包含了整个生成流程中需要用到的参数,这些参数包含:需要生成命令的实体的元数据信息、可用的ToolBar对象、可用的菜单、所有实体包含的命令、命令要用到的参数。

CommandAutoUIComponent 类表示整个生成流程中的可用的组件,这些组件都可以直接获取上下文对象中的内容。

CommandAutoUI

image

这里包含整个生成的流程所用到的核心对象:

CommandGroup 表示一个命令组,其中有组名。

GroupGenerator 是一个命令组的生成器,这里为它分配了以下职责:为命令组生成控件、把控件添加到上下文中。

GeneratableGroup 整合了上述两个对象,表示一个可生我生成的命令组。

GroupAlgorithm 表示某个命令的抽象的分组算法。注意,它只负责对某个命令进行分组。

GroupOperation 作为分组操作的执行者,调用分组算法对所有命令进行分组。它负责对所有的命令进行分组。

以上对象作为生成流程的核心对象,被CommandAutoUIManager进行组织并完成最终的界面生成:

image

GroupGenerators

image

图中列出了框架内置的可能用到的所有生成器。当然了,要扩展界面生成时,只需要编写新的子类就行了。

具体的内容在前面的“草稿”已经有所描述,在此不再赘述。

GroupAlgorithms

image

GroupAlgorithm 是策略模式的应用。

框架中内置三个分组算法:

DropDownListAlgorithm 表示把某一个命令分组到下拉组中。

DefaultAlgorithm 表示默认的一个命令一组的分组算法。

GenericItemAlgorithm 表示指定新的生成方式的分组算法。(添加这个类,是因为扩展时,80%以上情况只是为命令更换一种生成显示界面而已。)

 

整个流程用对象描述如下:

image


其它相关改动

    IParametrizedCommand 由原来的只支持 String 的 附加文本框命令变为更抽象的“需要参数的命令”。界面生成的控件在用户“填入”数据时,会组装出其所需要的参数,然后对它进行回调:

1
2
3
4
5
6
7
8
9
10
11
/// <summary>
/// 一种需要其它参数才能执行的命令。
/// </summary>
public  interface  IParametrizedCommand : ICommand
{
     /// <summary>
     /// 界面中输入的参数改变时,会通知这个Command参数值改变了。
     /// </summary>
     /// <param name="value"></param>
     void  NotifyParameterChanged( object  value);
}

 


总结

    这里再总结一个小的经验:

在开发过程中,为了简化代码,曾尝试使用设置属性的方式来设计构造函数的必要参数。但是属性设置并不是必需的,一旦忘记,则会需要调试才能找到问题所在,得不偿失。也就是说:

  • 不要以为类少就认为自己能记住其中的设置约定。最好是让编译器提醒你。 :)
  • 不要因为简化代码而去尝试违反一些好的设计规范。否则,不但可能写出不易调试的代码,而且影响后人的阅读。
目录
相关文章
|
6月前
|
敏捷开发 API
【sgCreateAPI】自定义小工具:敏捷开发→自动化生成API接口脚本(接口代码生成工具)
【sgCreateAPI】自定义小工具:敏捷开发→自动化生成API接口脚本(接口代码生成工具)
|
2月前
|
算法 JavaScript 前端开发
Fitten Code:自动生成代码注释工具
【9月更文挑战第02天】
383 7
|
4月前
|
SQL JSON 前端开发
中台框架模块开发实践-用 Admin.Core 代码生成器生成通用代码生成器的模块代码
可以看到这里只生成了后端接口,目前 v8.2.0 还不支持前端代码的生成,所以我们还需要手动去将对应版本的 前端代码 下载一份到项目中(只保留),并调整下目录结构,前端代码放到 admin-ui ,后端代码放到 admin-api 运行前后端项目,确认项目运行没问题后开始添加通用代码生成器模块代码。后续任意模块代码都可以参考步骤 1.后端项目引用关系配置 • 将生成的模块代码 ZhonTai.Module.Dev 拷贝到在新项目中 修改库中的引用,默认生成的 ZhonTai.Module.Dev.csproj 引用是相对源码的路径 • 所以需要修改下,直接引用 ZhonTai.Admin 的包
71 0
|
6月前
|
C++
win32编程 -- 通过空项目学习自动生成的代码框架
win32编程 -- 通过空项目学习自动生成的代码框架
39 0
|
6月前
|
SQL JavaScript 前端开发
若依框架代码自动生成器研究----表查询篇
若依框架代码自动生成器研究----表查询篇
480 0
|
6月前
|
Oracle Java 关系型数据库
Generator【SpringBoot集成】代码生成+knife4j接口文档(2种模板设置、逻辑删除、字段填充 含代码粘贴可用)保姆级教程(注意事项+建表SQL+代码生成类封装+测试类)
Generator【SpringBoot集成】代码生成+knife4j接口文档(2种模板设置、逻辑删除、字段填充 含代码粘贴可用)保姆级教程(注意事项+建表SQL+代码生成类封装+测试类)
113 0
|
存储 缓存 前端开发
《重构2》第十一章-重构API
《重构2》第十一章-重构API
110 0
|
测试技术
pytest学习和使用25-当看到allure的动态生成标题和描述的特性时,直言简直太灵活了(allure.dynamic使用)
pytest学习和使用25-当看到allure的动态生成标题和描述的特性时,直言简直太灵活了(allure.dynamic使用)
132 0
pytest学习和使用25-当看到allure的动态生成标题和描述的特性时,直言简直太灵活了(allure.dynamic使用)
|
测试技术 Python
python接口自动化(二十六)--批量执行用例 discover(详解)
我们在写用例的时候,单个脚本的用例好执行,那么多个脚本的时候,如何批量执行呢?这时候就需要用到 unittest 里面的 discover 方法来加载用例了。加载用例后,用 unittest 里面的 TextTestRunner 这里类的 run 方法去一次执行多个脚 本的用例。那么前边介绍那么多都是半道开始,半道出家,这篇就带大家从头到尾,一步一步给小伙伴们详细介绍一下。
258 0
python接口自动化(二十六)--批量执行用例 discover(详解)
|
测试技术 Go 数据库
Go开发技巧和踩坑分享 | 代码结构 调试技巧 配置文件 元数据
分享一下最近使用GoFrame开发go项目的经验分享。
178 0