|
CommonTemplate 架构指南 |
|
一. 包结构设计说明
设计原则:
高内聚:
重用发布等价原则(REP): 包的重用粒度应该与可发布粒度相同,可发布是指可单独打成组件包(jar),并且组件包能符合开闭原则(OCP)。
共同重用原则(CRP): 包中的类应该有同样的重用可能性,也就是紧密协作的类应该放在一个包。
共同封闭原则(CCP): 包中所有类应该对同一类性质的改变作出相同反应(全改或全不改),若改动则变化应在包内终止而不传播到其它包。
低耦合:
无环依赖原则(ADP): 包之间不出现相互依赖和循环依赖,这是最基本应做到的。
稳定依赖原则(SDP): 被依赖的包应该总是比依赖者更稳定,也就是不要让一个稳定的包依赖于不稳定包。
稳定抽象原则(SAP): 越稳定的包应该越抽象。 (注:参见此节后面的计算方式)
CommonTemplate总体包结构:
(0) util包 (通用工具包)
位置:org.commontemplate.util及其子包
职责定义:相当于java.util的扩展,实现一些其它通用功能,它只依赖于JDK,不依赖于CommonTemplate引擎。
(注:以下包都依赖于JDK相关包及上面的util包,不再说明)
(1) core包 (核心API包)
位置:org.commontemplate.core及其子包
职责定义:模板语言的API包,定义模板各元素间的关系,资源管理接口等,全部为接口或抽象类,围绕Template和Context展开。
入口类:org.commontemplate.core.Factory
(2) engine包 (引擎实现包)
位置:org.commontemplate.engine及其子包
职责定义:模板引擎的实现,处理模板加载解析等,实现core包的所有接口,此包隐藏实现细节,只暴露Engine类,便于后期优化,Engine实现了core包的Factory,core包的其它相关接口都可以通过接口间导航获取。
依赖于:core包, config包
入口类:org.commontemplate.engine.Engine
(3) config包 (配置SPI包)
位置:org.commontemplate.config及其子包
职责定义:留给第三方的扩展接口,以Configuration接口为中心,Configuration定义了engine包所需配置的getXXX()方法,但不包括setXXX()等,因为SPI不应限制实现类的注册方式。
依赖于:core包
入口类:org.commontemplate.config.Configuration
(4) standard包 (标准参考配置实现包)
位置:org.commontemplate.standard及其子包
职责定义:config包的标准参考实现,包括指令及操作符等语法的定义相关配置,并提供Configuration相应的setXXX, addXXX等注册方法类。
依赖于:core包, config包
入口类:org.commontemplate.standard.ConfigurationSettings
(5) ext包 (扩展配置实现包)
位置:org.commontemplate.ext及其子包
职责定义:config包的扩展实现,用于特定场景的实现,以及第三方适配实现等。
依赖于:core包, config包, standard包
(6) tools包 (Client使用工具包)
位置:org.commontemplate.tools及其子包
职责定义:一些常用的客户端工具以及与其它框架集成相关类,这些已不属于CommonTemplate引擎的范围内,只是为了方便用户使用而提供。
依赖于:core包, engine包, config包, standard包
入口类:org.commontemplate.standard.PropertiesConfigurationLoader
总体包结构图如下: (注:隐抑了继承包相同于被继承包的依赖关系)
不稳定度与抽象度的计算与关系:
(1) I = Ce / (Ca + Ce)
I: Instability (不稳定度)
Ca: Afferent Coupling (传入依赖,也就是被其它包依赖的个数)
Ce: Efferent Coupling (输出依赖,也就是依赖其它包的个数)
(2) A = Na / Nc
A: Abstractness (抽象度)
Na: Number of abstract classes (抽象类的个数)
Nc: Number of classes (类的个数,包括抽象类)
(3) D = abs(1 - I - A) * sin(45)
D: Distance (偏差)
I: Instability (不稳定度)
A: Abstractness (抽象度)
设计最理想状态是D为0,也就是I-A交点分布在绿线上
比较合理的设计度量为:D < 0.2
CommonTemplate所有包(包括子包)的I-A交点分布如下: (注:D < 0.2 的为绿色,否则为黑色)
黑色(不合格)的是:
util包 (这个包必然如此,因为作为工具包,它被依赖过多,但抽象度却不够)
standard包的一些子包 (待调整)
二. 核心包设计说明
核心包采用接口驱动设计,全部为接口或抽象类,只考虑需求与关系,忽略实现。
并按领域驱动设计将其分为三个域:
(1) Template域 (实体域)
范围:包括Resource, Template, Element, Directive, Expression, Operator等。
职责定义:用于表示一个具体的模板,此域是整个引擎的中心,所有功能围绕其展开。
线程安全性:Template域的领域模型被设计成线程安全的(不变类),保证在多线程中单实例重用。
(2) Context域 (会话域)
范围:包括Context, GlobalContext, LocalContext等。
职责定义:Context域负责状态及外部资源的管理。
线程安全性:Context域是非线程安全,应该为每次执行创建新的实例(即在线程栈内使用)。
(3) Factory域 (服务域)
范围:包括Factory, ContextFactory, TemplateFactory等。
职责定义:Factory域负责管理Template域和Context域的生命周期。
线程安全性:Factory域是线程安全的(内部同步),可单例重用。
核心包设计图如下: (注:省略了Element对Context和Expression对VariableResolver的依赖关系)
四色原型概要[Coad95-97]
红色:moment-interval (瞬时状态,会话)
黄色:role (主动域,操作者,服务等)
绿色:party, place or thing (被动域,实体,值对象等)
蓝色:catalog-entry-like description (分类或入口标识)
三. 引擎包设计说明
引擎包使用配置包SPI实现核心包API。
引擎包隐藏所有实现细节,只暴露Engine, TemplateEngine, ExpressionEngine,便于后期优化。
引擎按重用粒度分级控制:
(1) 通常都直接用Engine,它提供所有功能,包括解析器和Context资源管理等。
(2) 如果使用第三方实现的Context(通常用在与其它模板工具适配时),则可以只用TemplateEngine,提供模板解析功能。
(3) 如果只用表达式功能(通常是作为动态表达式求值工具时),则可以只用ExpressionEnine,提供表达式解析功能。
引擎包设计图如下:
四. 配置包设计说明
配置包用于向引擎供给数据,按引擎包的格局分三个层次:
(1) 表达式解析配置
(2) 模板解析配置
(3) 资源管理配置
配置包设计图如下:
|
|