赞
踩
本文源自《PoEAA》,如预知详细内容请阅读原书
好的决策不是一成不变的。架构重构很难,人们也经常忽视它的代价,但是并非不可能。我给的建议就是:即使你对极限编程不感兴趣,你还是应该认真考虑三方面的技术实践:持续集成、测试驱动开发和重构。这些技术虽然不是万能的灵丹妙药,但他们能够帮助你在需要的时候更容易地改变你的系统。除非你比迄今为止我见过的人更能干或更走运。
这个过程可以从决定领域逻辑方法开始。主要的可选模式是事务脚本、表模块以及领域模型。
这三种模式中最简单的事事务脚本模式。它比较符合大多数人仍然习惯的过程模型。它将每种系统事务的逻辑很好地封装在功能完善的脚本中,而且比较适合于在关系数据库之上的构建。它的主要问题是对复杂业务逻辑的支持不够,尤其不善于处理重复代码。如果你所面临的是一个简单的企业目录应用或只有简单定价结构的购物车应用等,事务脚本就足够了。但是如果业务逻辑更复杂,开发困难就会呈指数增加。
这三种模式中最复杂的事领域模型模式。但是,如果应用比较简单,用事务脚本就足以应付,为什么还要费时劳神地用这个模式?而且,就我本人的经验而言,如果面临的问题真的非常复杂,那么处理领域模型之外,没有其他模型能做的更好。如果你已经习惯使用领域模型,那么对于简单的问题,也很容易解决。
当然,领域模型也有其缺点。最大的缺点就是难以学会如何使用领域模型。领域模型的第二个缺点就是它于数据库的连接。
表模块事这两个极端之间一个比较好的折中。在处理领域逻辑上,它比事务脚本强。虽然它在处理复杂领域逻辑上不如领域模型,但这对于关系数据库和其他一些东西而言,它还是游刃有余的。
从这里我们不难看出,工具也会影响到应用到架构,有时可以根据架构来选取工具,而且,从理论上说你应该那么做。在实践中,我们必须让架构和工具相匹配。在这三种模式中工具对表模块的作用最大,好的工具支持将能使你如虎添翼。对于.Net环境来说,表模块就非常合适。
最简单的事务脚本包含其自身的数据库逻辑,但是,即使在最简单的情况下,我也会尽量避免这样做。分离数据库,使得领域逻辑和数据源逻辑这两部分的界限划分变得有意义,因此,即使是在最简单的应用里,我也会这样分离。此时,可供选择的数据库模式包括行数据入口和表数据入口。
这两者中选择哪一个,很大程度上取决于实现平台的方便以及系统未来的发展方向。在行数据入口中,每个记录都通过显示的接口读入到一个对象中。在表数据入口中,程序员可以少写一写代码,因为他不需要写那么多存取器代码就可以读取数据,但是编程接口确实相对隐式的,这些接口依靠对记录集的访问(类似于映射)。
最关键的决策取决于所用开发平台的其余方面。如果所用的平台包含很多支持记录集的工具,特别是UI工具和事务性的断接记录集,则选择的天平就会偏向表数据入口。
也可以考虑工作单元,但一般来说,在脚本中跟踪变化的部分很容易。在这里,无需关心大多数并发问题,因为脚本基本上对应一个系统事务。因此,可以将整个脚本封装在单个事务中,异常一般发生在一个请求将数据读取出来编辑、而下一个请求试图对变化进行保存的情况下。这种情况下,一般使用乐观离线锁。它不但容易实现,而且可以满足用户的需求,并避免了由于挂起会话所导致的大面积加锁情况,
选择表模块最主要的原因是有一个好的记录集框架。此时,就需要一个与记录集配合良好的数据库映射模式,这就是表数据入口,这两个模式配合得天衣无缝。
使用了这个模式后,在数据源层几乎不需要再加什么其他功能。比较理想的情况下,记录集中都内置了某种形式的并发控制机制,这使得它成为工作单元,从而进一步降低了开销。
如果领域模型相当简单,例如只有十几个与数据库相关的类,则活动记录就可以了。如果希望耦合更松一些,则可以用表数据入口或行数据入口。做不做这种分离都不会带来太大的工作量。
随着复杂度的进一步增加,可以考虑使用数据映射器,这种方法将确保领域模型尽可能与其他各层相互独立。但是数据映射器也是实现起来最复杂的一种模式。除非你的开发队伍非常强劲,或者能够找到一些简化映射的方法,否则我强烈建议你使用一种映射工具。
表现层再很多方面都独立于其下层的选择。
如果你走HTML路线,就必须决定如何组织你的应用。我建议使用模型-视图-控制器作为设计基础。
如果你使用的是Visual Studio,最简单的方法是用页面控制器和模版视图。如果你使用的是Java,还可以考虑一些Web框架,比较流行的如Struts,它会帮助你运用前端控制器和模版视图。
如果选择范围比较宽裕,且你的站点更多的是面向文档,那么推荐使用页面控制器,特别是当既有静态页面又有动态页面的时候。如果站点的导航机制和UI更为复杂,则可以考虑使用前端控制器。
关于视图主要有两种选择:模版视图和转换视图。这主要取决于开发组编程时使用的是服务器页面还是XSLT。如果你开发的是一个有多种表现形式的站点,请考虑使用两步视图。
无论在什么情况下使用实体Beans,都应该尽量避免给它们一个远程接口。我一直不知道首先给实体Beans定义一个远程接口的原因何在。实体Beans一般都用在领域模型或行数据入口中。无论哪种情况,它们所需要的都是细粒度的接口。但是远程接口一般都是粗粒度的,因此尽量使你的Beans本地化。
正是由于模块化和可移植性的原因,很多人在开发业务逻辑时都尽量避免使用存储过程。我比较赞同这一观点——除非有很强的性能要求。
使用存储过程的一般方法是在表数据入口方式下控制数据库访问。
Brown分层模型
Brown | Fowler |
---|---|
表现层 | 表现层 |
控制层/中介层 | 表现层(应用控制器) |
领域层 | 领域层 |
数据映射层 | 数据源层(数据映射器) |
数据源层 | 数据源层 |
Core J2EE分层模型
Core J2EE | Fowler |
---|---|
客户层 | 运行于客户端的表现层(例如,胖客户系统) |
表现层 | 运行于服务器端的表现层(例如,HTTP处理程序、服务器页面) |
业务层 | 领域层 |
集成层 | 数据源层 |
资源层 | 需要与数据源层通信的外部资源 |
Microsoft DNA分层模型
Microsoft DNA | Fowler |
---|---|
表现层 | 表现层 |
业务层 | 领域层 |
数据访问层 | 数据源层 |
Marinescu分层模型
Marinescu | Fowler |
---|---|
表现层 | 表现层 |
应用层 | 表现层(应用控制器) |
服务层 | 领域层(服务层) |
领域层 | 领域层(领域模型) |
持久层 | 数据源层 |
Nilsson分层模型
Nilsson | Fowler |
---|---|
顾客层 | 表现层 |
顾客帮助层 | 表现层(应用控制层) |
应用层 | 领域层(服务层) |
领域层 | 领域层(领域模型) |
持久访问层 | 数据源层 |
公共存储过程层 | 数据源层(可能包含一些领域层) |
私有存储过程层 | 数据源层(可能包含一些领域层) |
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。