设计模式综和实战项目x-gen系列一

1 X-gen的项目背景

1.1 项目背景

很多做应用项目的朋友都会有这样的感觉:项目越来越大,模块越来越多,但是大多数都是重复或者相似的做法,至少每个模块的基础部分的实现是差不多的,比如CRUD(增删改查)功能的实现,又比如翻页功能的实现等等。

因此,很多朋友都在想办法解决这个问题,如何能够减少这些重复劳动,让自己把有限的时间和精力投入到具有创意或挑战的功能实现上。

很快地,大家便根据自己的需要,结合公司已有的系统架构和公共功能,制作出了符合自己需要的小应用,可以实现根据配置文件或者是数据库定义来生成应用模块,并带上增删改查的功能实现。

通常的实现思路是,先根据本公司实现增删改查的方式来制作模板文件,然后把模板里面需要变化的部分改成变量,然后通过配置文件去配置这些需要变化的值,然后在程序运行的时候,由程序去读取配置文件的值,把这些值替换到模板中,从而得到需要生成的文件,然后把生成好的文件输出出来就好了。

一切看起来是那么完美,从此不需要再去写每个模块的基础部分了,可以根据配置或数据库定义来生成这些基础部分,然后在此基础之上,进行业务功能的开发就可以了。

通常这种程序,由于是公司内部专用,因此会实现得非常简单,很多复杂多变的状况也就不再去考虑了,只要满足自己的需要即可。

1.2 面临的问题

看上去很不错吧,但是真的很完美了吗?考虑一下如下的问题:

Ø如果生成的配置文件需要发生变化
那么相应的读取配置文件的程序需要变化;同时使用这些数据的程序也需要变化

Ø如果模板文件需要发生变化
那么读取模板文件的地方需要发生变化,同时,运行中把参数数据设置到模板的程序也需要发生变化。

Ø如果调用逻辑或调用顺序需要发生变化
那就需要修改调用部分的程序来适应新的变化

Ø如果输出格式需要发生变化
那就只好重新写代码来实现新的输出格式

类似这样的问题还有很多,这里就不一一列举了。

由于很多这样公司内部使用的工具型应用,是按照公司现有的开发模式来实现的,大都实现得非常简单和僵硬,对于这些变化适应能力是非常差的。

而上述这些变化,是经常发生的,因此,很多公司都会有人专门负责维护这样的内部应用,不断更改这些程序来适应新的应用的需要。

而且,由于生成的调用过程、生成配置、生成模板以及最后生成文件是搅和在一起的,因此改动起来非常困难。

1.3 X-gen出场

因此我们需要一个项目,来把生成应用的核心部分独立出来,形成公共的应用,让变化的部分从应用中分离出来,让程序人员可以根据需要进行配置和扩展,从而适应各种应用的需要。

X-gen就是这样一个应用。X-gen分成两个部分,一个部分是核心框架,用来实现生成应用的公共部分;另外一个部分就是自定义模板部分,按照程序人员的需要来制定模板,几乎所有能重复使用的功能都可以通过X-gen生成,没有什么使用限制。

注:由于中文表达中存在很多歧义,比如:“生成应用配置”,到底是说产生应用的配置文件呢?还是指的x-gen这个生成应用的配置?因此,本书后面提到生成应用的时候,都以x-gen来代替。某些地方提到生成的时候,为避免歧义,用“generate”来代替。

2 系统功能

2.1 系统整体功能概述

x-gen是一个能按照模板和配置去生成结果的通用框架,设计精巧,结构灵活,平台开放,支持模板自定义,支持配置方式自定义,支持生成方式自定义,甚至可以自定义generate的过程。X-gen的核心是一个通用的生成调用框架,本身并不约定任何需要生成的东西,因此几乎可以满足所有朋友的各种generate需求。

x-gen首先要解决根据什么来生成的问题;其次要解决如何生成的问题,同时还要解决在生成的时候如何利用外部主题的问题;然后要解决生成结果的问题,包括最终生成成为什么格式,以及把结果输出到什么地方等问题。

2.2 配置管理(genconf)功能概述

x-gen是按照配置来generate的,因此对于x-gen,配置是非常重要的一个部分。

X-gen是一个通用的框架,它本身并不固定要求配置的格式,也不要求配置的来源,因而它也不固定获取和解析配置数据的程序。虽然x-gen默认提供了对xml配置的支持,但是可以通过注册新的provider来提供对新的配置方式的支持。

x-gen可以完全由开发人员自己来制定配置的方式、配置的地方、配置的格式,以及如何获取这些配置数据,如何解析这些配置数据等。并能够以很简单的方式插接到x-gen的核心框架中。

2.3 分发调度(dispatch)功能概述

分发调度提供接受用户请求的入口,然后根据用户请求的内容,去获取相应的配置数据,获得户配置的数据过后,就按照配置的要求来发出命令,要求按照这些配置数据来完成generate的功能。

在每一个具体命令的实现中,先动态组合需要完成的generate的功能,然后就把这些功能交给generate的代理去完成。

也就是说分发调度只是负责接收用户的任务,然后把任务组合好,最后分配出去这些功能,只是起到一个调度的作用,本身并不处理用户的请求功能。

2.4 生成代理(genproxy)功能概述

生成代理是一个介于生成调度(dispatch)和真正生成(geninvocation)之间额外的附加层,目的是能够根据需要切换不同的代理,比如生成调度根据配置,需要通过远程来生成,那么就需要远程代理,远程访问的方式可能是rmi或webservice等等

2.5 具体调用(geninvocation)功能概述

首先根据用户配置的数据去获取相应的theme的数据,然后根据用户配置的theme的调用过程,用户配置的generate处理的程序来进行具体的generate。通常是把用户配置的参数数据,按照一定的规则与theme的模板相结合,从而得到需要生成的结果。

但是这整个过程是开放的,可以由开发人员根据自己generate的需要来配置,从而动态的运行整个generate过程。

2.6 模板管理(template)功能概述

x-gen本身是按照模板和配置来生成,那么模板怎么来呢?

x-gen的核心框架本身不绑定任何模板,而是支持模板的自定义,通过插件形式,把用户自定义的模板结合到x-gen里面来。

由于模板的配置会有很多个,通常会把多个相关的模板组合在一起,统称为主题,也就是theme,今后我们就不说模板了,而是说x-gen根据主题/theme来生成。

目前x-gen缺省提供一个示例性质的simple主题。

模板管理的功能就是负责获取相应的模板数据,并对这些模板的数据进行管理,在外部需要这些模板数据的时候,可以访问模板管理提供的接口来获取。

对于模板的格式,目前x-gen规定固定是文件;对于theme自身的配置,目前x-gen规定固定是xml格式,并由x-gen提供默认的解析程序,这主要是为了让theme更好的实现“即插即用”的功能,而且也确实没有必要让theme的配置有很多的形式,theme的配置跟theme是紧密联系的。

2.7 生成输出(output)功能概述

具体调用(geninvocation)运行完成后,会产生generate的结果,这些结果如何输出?输出到什么地方?输出成为什么格式等等问题,都由生成输出来负责。
生成输出本身并不固定任何的输出要求,开发人员完全可以在外部来定义输出的格式,输出的地方,以及如何输出等,只需要最后在theme的配置中注册新的outtype即可。目前x-gen提供了最简单的输出成为普通文本类型的文件的功能。

3 外部主题功能概述

3.1 外部主题功能概述
外部主题是独立于x-gen核心框架之外的,完全由开发人员根据需要来制定,通常里面会包含generate所需要的所有原始模板文件,跟模板文件对应的解析和生成的辅助程序,生成处理的Action处理程序,还有theme的配置文件,一般这几个是必不可少的;其次是根据需要,由开发人员扩展的功能,比如:在进行生成处理前后需要额外添加的功能,自定义的输出类型等等。
外部主题决定了按照什么来生成、如何生成以及生成成为什么东西的具体信息,是提供给x-gen核心框架使用的重要数据。

4 模块划分

根据前面的功能描述,可以把x-gen分成如下模块:

1:配置管理模块

(1)模块边界
不管配置数据从何而来,不管如何获取配置数据,只管根据provider得到配置数据,然后缓存管理这些数据,并对外提供访问这些数据的接口,另外配置管理的配置数据的对象结构是固定的,由x-gen预先定义好,也就是数据的来源任意,但是最终的结果对于x-gen来说是一样的。
默认提供一个读取xml配置文件的provider实现。
(2)输入输出
输入:
由theme或者是由x-gen的客户端来提供provider;由开发人员确定三类配置的配置数据。
输出:
模块外部通过接口来访问配置的数据。

2:分发调度模块

(1)模块边界
不关心配置数据如何得到,也不关心究竟请求要求的功能如何执行。只是负责接收用户请求,把请求转化成要执行的功能,然后通知代理去执行这些功能。
(2)输入输出
输入:
客户请求,可能会传入可以获取核心框架配置的provider;所需的配置数据来自于配置管理模块。
输出:
把需要generate的功能告诉生成代理

3:生成代理模块

(1)模块边界
不关心配置数据如何得到,不关心要执行些什么功能,也不关心究竟这些功能如何执行。只是负责根据分发过来的任务,代理调用真正执行生成的模块。
(2)输入输出
输入:
分发调度模块分发过来的任务,当然会带着所需的配置数据和具体的命令。
输出:
代理启动真正负责执行生成的模块。

4:具体调用模块

(1)模块边界
不关心配置数据如何得到,不关心要执行些什么功能,也不关心究竟这些功能如何执行,更不关心执行完的结果如何处理。

只是负责根据按照核心框架制定的具体调用的功能步骤,依次调用执行,当然过程中会需要使用模板的数据,然后负责在generate过后,通知生成输出模块进行输出。

(2)输入输出
输入:
生成代理模块传递过来的任务,当然会带着所需的配置数据和具体的命令;以及开发人员扩展的生成的Action处理、以及Action执行前后的装饰器功能;会通过模板管理模块去获取模板的数据。

输出:
有了generate结果后,自动通知生成输出模块进行输出。

5:模板管理模块

(1)模块边界
不关心模板数据被如何使用。只是按照x-gen的约定,从theme中读取相应模板的数据,然后把这些数据缓存起来,并提供模块外部访问这些数据的接口。

(2)输入输出
输入:
配置中需要的theme的模板文件的路径。
输出:
提供模块外部访问这些数据的接口。

6:生成输出模块

(1)模块边界
不关心需要生成什么数据,也不关心具体生成到哪里、生成成为什么格式以及如何真正实现输出。只是按照配置中的约定,执行相应的负责生成输出的对象的方法,把从具体调用模块传递过来的数据生成出去。

(2)输入输出
输入:
配置中相应的数据;具体调用模块传递过来的数据。
输出:
最终用户想要生成的结果。

7:公共工具模块

模块边界
跟具体业务不相关,只是提供某些工具性的功能,比如:文件的读写、xml文件的通用读取等等。

说明:本文由微信公众号——架构设计一起学推出

点击“阅读原文”,将有更多收获哦!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章