结合领域驱动设计的SOA分布式软件架构,你还在为这些烦恼?( 四 )

< 1000)_order.Favorable = _order.Price * 0.1;if (point >= 1000if (point > 2000)_order.Favorable = _order.Price * 0.3;}//如果价格在98元以上 , 可免运费 。 其余运费为10元private void FreightageAccount(double price){if (price >= 98)_order.Freightage = 0;else_order.Freightage = 10;}}}你可能会说 , 在这个业务流程中 , 除了积分优惠Person.Point以外 , 其他的业务都只与Order的属性有关 , 按照充血型模型的方案 , 完全可以把这些业务放到Order的方法当中 , 而把积分优惠独立成为一个服务 。 但在下在很多的开发过程中发现 , 为模型附上动作会带来一连串的问题 , 好像你不知道哪些操作应该在模型动作上实现 , 哪里应该在服务中实现...... 。 对于这些无休止的争论不会因为这里的一个小例子而停止 , 但在这里我会坚持使用贫血型模型,利用服务来完成所有的动作 。
再举一个例子:在最后结单的时候Order表里会产生订单号码OrderNumber和下订日期Delivery , Person表的积分也会加上订单总价的点数 。 对应这个操作 , 也可以单独开发一个PaymentManager服务类进行管理 。
namespace Business.Service.DomainService{public class PaymentManager{//下单结算public void Payment(Order order,Person person){//确定下单 , 建立订单号order.OrderNumber = Guid.NewGuid().ToString();order.Delivery = DateTime.Now;//增加积分if (person.Point.HasValue)person.Point += (int)order.TotalPrice.GetValueOrDefault();elseperson.Point = (int)order.TotalPrice.GetValueOrDefault();}}}利用领域层的服务 , 使得每个Manager服务类的职能非常明确 , 业务管理起来也十分地方便 , 领域层可以随着业务的改变而灵活变动 。 而且领域层具有 “高内聚 , 低耦合” 特性 , 它并不依赖其它任何一层 , 而只是把业务逻辑包含在里面 。
六、工厂模式FactoryFactory是常用到软件开发模式 , 在网上像简单工厂、工厂方法、抽象工厂等开发模式的资料都到处可寻 , 可这并不是领域驱动设计的主题 。 在这一节里 , 我主要想介绍Factory的使用时机 。
并非生成所有对象的时候 , 都需要用到工厂模式 。 在生成简单对象的时候 , 可以直接利用构造函数来代替工厂 , 也可以添加工厂方法来生成对象 。 但如果在生成对象时 , 内部属性之间存在一系统复杂的业务规则的时候 , 就可以把生成方法独立到一个Factory类里面 。 这时候客户端无需理会潜在逻辑关系 , 而直接通过这个Factory来生成相应的对象 。
举个例子 , 在新建Order的时候 , 业务上规定运费是总体金额的1% , 折扣规定是7.5折......。 如果由客户端新建一个对象Order , 然后为这些属性负值 , 那相关的业务逻辑就会暴露在外 。 这时候就可以使用Factory模式 , 把属性之间的关系封装到Factory之内 , 客户端通过Factory就能轻松地生成Order对象而无需要理会复杂的内部关系 。
结合领域驱动设计的SOA分布式软件架构,你还在为这些烦恼?文章插图
至于较复杂的Factory模式 , 在此不多作介绍 , 各位可以在网上查找相关资料 。
七、细说应用层1. SOA系统中应用层的特点
在开发SOA分布式系统的时候 , 应用层是一个重点 , 它主要有两个作用 。
第一 , 应用层主要作用是协调领域层工作 , 指挥领域对象解决业务问题 , 但应用层本身不会牵扯到业务状态 。
第二 , 在SOA系统当中应用层是数据运输中心和信息发放的端口 , 担负着数据转换与数据收发的责任 。
它有以下的特点:

  • 粗粒度
分布式系统与普通网站和应用程序不同 , 因为它假定外界对系统内部是毫无了解的 , 用户只想输入相关数据 , 最后得到一系列计算结果 。 所以我们应该把计算结果封装在一个数据传输对象(DTO)内 , 实现粗粒度的传递 , 这是一般项目与SOA系统在服务层的一个最明显的差别 。想想如果一个页面需要同时显示一个顾客的个人资料、某张订单的详细资料 , 那将要同时获取Person、Order、OrderItem三张表的信息 。 在普通系统的开发过程中 , 这并不会造成太大问题 , 但在使用远程服务的时候 , 如果用三个方法分别获取 , 那将会造成不少的性能损耗 。 特别是在分布式开发系统中 , 应用层与表现层之间是实现分离的 , 更多时候两者是由不同部门所开发的模块 , 表现层不会了解应用层中的逻辑关系 , Person , Order , OrderItem三样东西在表现层看来 , 也就是同一样东西 , 那就是返回值 。 所以在系统内 , 应该把多张表的信息封装在一个DTO对象内 , 通过应用层一个远程方法一次性返还 。 使用粗粒度的数据元素是分布式系统的一个特点 。