最近找数据,看到了博客园在不久之前,办了一个架构分享的活动:.Net项目分层与文件夹结构大全。看完之后觉得获益良多,接着也忍不住手痒,开始整理属于自己的分层架构:「CLK Architecture」。
CLK Architecture的设计,是以DDD(Domain-driven design)概念精神做为核心,并且选用微软.NET相关技术来实作。期望提供开发人员,在开发.NET相关应用程序时,有个基础的分层架构、命名惯例可以参考,省去每个项目都要重新思考设计的脑力消耗。另外CLK Architecture也做为开发技术的索引地图,在每个不同的分层中,推荐可选用的各种技术框架,用以降低整个系统开发的评估成本。
在CLK Architecture中,有几个要点需要先做说明:
Domain Layer封装提供企业逻辑的领域对象、以及领域对象进出系统的边界接口。
在DDD(Domain-driven design)的概念精神里,系统中的企业逻辑可以被捕捉并且描绘出领域模型,再由领域模型去分析设计出对应的领域对象,用以在计算机系统中提供解决方案。而计算机系统中所执行的的领域对象,免不了需要将数据存放到数据库、或是从系统外部取得数据,这些与数据库、系统外部交换数据的功能,会被分析设计为对应的边界对象,然后再套用IoC模式来产生边界接口,用以切割领域对象与边界对象的相依。在CLK Architecture中这些领域对象(Entity、ValueO bject...)、边界界面(IRepository、IFactory...),会被分门别类、封装成为Domain Layer的内容。
对于领域模型、领域对象的捕捉与设计,有兴趣的开发人员可以参考下列数据:
Data Access Layer封装领域对象进出系统的边界对象。
在DDD(Domain-driven design)的概念精神里,系统中的领域对象与数据库、系统外部交换数据的功能,会被分析设计为对应的边界对象,然后再套用IoC模式来产生边界接口,用以切割领域对象与边界对象的相依。在CLK Architecture中这些边界对象(Repository、Factory...),会被分门别类、封装成为Data Access Layer的内容。
Persistence用来封装系统与数据库交换数据的边界对象,这些边界对象实作透过IoC模式所产生的边界接口,用以提供领域对象进出数据库的功能。
在CLK Architecture中是采用领域对象来做为进出数据库的数据单位,而企业中比较常见的数据库是关系数据库,在领域对象与关系数据库之间存在着「阻抗不匹配」的问题,领域对象是没有办法直接进出关系数据库的。 开发人员可以选用下列O/R Mapping框架、或是人工建立O/R Mapping相关程序代码,来实作系统中领域对象进出数据库的功能。
Persistence用来封装系统与Config文件交换数据的边界对象,这些边界对象实作透过IoC模式所产生的边界接口,用以提供存取Config文件的功能。
在系统中除了将数据存放到数据库之外,也常常会需要透过Config档的方式来存放一些设定数据,让布署程序的过程能够更加的便利。 开发人员可以选用下列框架、或是人工建立相关程序代码,来实作系统中存取Config文件的功能。
ProxyModel用来封装系统与子系统交换数据的边界对象,这些边界对象实作透过IoC模式所产生的边界接口,用以提供存取子系统的功能。
在系统中除了将数据存放到数据库、Config文件之外,某些情景也会透过TCP、WCF、Web API、函式库引用...等等接口来与子系统交换数据,藉以重用子系统的功能。 开发人员可以套用Adapter、Proxy...等等模式来包装子系统,来实作系统中存取子系统的功能。
Interface Layer封装与用户互动的用户接口对象、以及与远程系统互动的通讯接口合约。
在DDD(Domain-driven design)的概念精神里,与用户互动的用户接口,会被分析设计为对应的用户接口对象。而在用户之外,系统也需要透过通讯接口来提供功能给远程系统使用,这些与远程系统交换数据的通讯接口,会被分析设计为提供通讯功能的通讯接口对象、以及提供通讯描述的通讯接口合约。在CLK Architecture中这些用户接口对象、通讯接口合约,会被分门别类,封装成为Interface Layer的内容。
View用来封装系统与与用户互动的用户接口对象,这些用户接口对象会透过网站页面、应用程序窗体...等等方式,来接受用户的输入、并且数据呈现给用户。
关于用户接口的开发与设计,应该依照项目需求、人力配置来做选择,开发人员可以参考下列数据来学习:
ServiceModel用来封装系统与远程系统交换数据的通讯接口合约,这些通讯接口合约依照选择的技术框架,会以不同形式存在于系统之中。而通讯接口合约如果是以程序代码的方式存在于系统之中,这些通讯接口合约中所使用的各种数据传输对象(Data transfer object),也必须以程序代码的方式存在于系统,并且同样封装成为ServiceModel的内容。
下列说明几种以不同形式存在的通讯接口合约:
关于通讯接口合约、数据传输对象的开发与设计,应该依照项目需求、人力配置来做选择,开发人员可以参考下列数据来学习:
Application Layer封装与用户互动的用户领域对象、以及与远程系统互动的通讯接口对象。
在DDD(Domain-driven design)的概念精神里,系统中除了包含企业逻辑之外、也包含了提供用户接口使用的功能逻辑(例如:验证、授权、数据组合...等等),这些功能逻辑会被分析设计为对应的用户领域对象。而在用户接口之外提供给远程系统使用的通讯接口,也会被分析设计为提供通讯功能的通讯接口对象、以及提供通讯描述的通讯接口合约。在CLK Architecture中这些用户领域对象、通讯接口对象,会被分门别类,封装成为Application Layer的内容。
ViewModel用来封装提供用户接口功能逻辑的用户领域对象,这些用户领域对象实作用户接口对象所需要的功能逻辑,用以提供功能给用户接口对象使用。
在系统中的用户接口会提供验证身份、授权功能...等等功能给用户,这些功能不属于企业逻辑所以不会被封装成为领域对象,会被分析设计为用户领域对象。而在用户接口中常常需要的数据对象不是单一领域对象,需要由多个领域对象组合成的数据对象,这些数据对象、数据对象组合与分解也被划分在用户领域对象之中。
这边要特别说明的是,如果目标系统的企业逻辑是处理验证身份、授权功能的功能,那在目标系统中封装这些功能的对象,会被划分在领域对象之中。也就是说,一个封装功能的对象是属于领域对象、用户领域对象,应该依照是否为目标系统的企业逻辑来区分。
ApplicationModel用来封装系统与远程系统交换数据的通讯接口对象,这些通讯接口对象实作系统所包含的通讯接口合约,用以提供功能给远程系统使用。
在系统中的通讯接口会提供功能给远程系统使用,这些功能不属于企业逻辑所以不会被封装成为领域对象,会被分析设计为通讯接口对象。而在通讯接口中用来封装通讯数据的数据传输对象(Data transfer object),会是由一个到多个领域对象来组合、或是分解为一个到多个领域对象,这些数据传输对象的组合与分解也被划分在用户领域对象之中。
Host Layer封装系统中生成与组合各个Layer的功能,并且以应用程序、网站、系统服务...等等方式来设计为宿主程序,用以执行之后在计算机系统中提供解决方案。
关于宿主程序的开发与设计,应该依照项目需求、人力配置来做选择,开发人员可以参考下列数据来学习。(括号内容为CLK Architecture的命名惯例)
Infrastructure Layer封装系统中共享的功能模块。
提供Dependency Injection的功能模块。开发人员可以选用下列框架、或是人工建立相关程序代码,来实作系统中Dependency Injection的功能。
提供O/R Mapping的功能模块。开发人员可以选用下列框架、或是人工建立相关程序代码,来实作系统中O/R Mapping的功能。
提供Logging的功能模块。开发人员可以选用下列框架、或是人工建立相关程序代码,来实作系统中Logging的功能。
Other Layer封装不属于在系统架构的设计范围,但却是系统开发设计时,必定会建立的功能模块。
提供系统测试的功能模块。系统测试在近代软件开发中扮演的角色越来越重要,有兴趣的开发人员可以找寻相关数据来学习。
提供系统展示的功能模块。在系统开发的各个阶段都会需要产生一些展示项目,用来验证功能模块是否符合需求。