.NET应用架构设计—适当使用活动记录模式代替领域模型模式

阅读目录:

  • 1.背景介绍
  • 2.简单介绍领域模型模式、活动记录模式
  • 3.活动记录模式的简单示例及要点
  • 4.总结

1.背景介绍

对软件开发方法论有兴趣的博友应该发现最近“领域驱动设计”慢慢的被人发现被人实践起来,园子里也慢慢有了DDD的学习气氛和宝贵实战经验的分享。其实之前我也痴迷于DDD,为什么会痴迷于它并不是因为它是所谓的新技术,也不是因为各种对它的炒作,而是我觉得我找到了能解放我们进行企业业务系统开发的方法论。

DDD可以很好的指导我们开发可靠的软件系统,尤其是现在的企业业务复杂多变的情况下,使用DDD可以很好的随着业务变化不断的重构现有的领域模型,最为重要的是我觉得DDD是能够很好的实施敏捷价值观的软件开发方法论。

如果你想重构、测试你所写的业务代码,少不了对代码进行适当的罗动,如果没有一个好的结构让你存放你所提取出来的代码是比较无奈的。包括现在敏捷软件开发方法论中最重要的TDD方法论更加的依赖代码的结构是否能够允许进行重构,如果你的结构是很死板的,扁平化的其实很难实施TDD,你会发现你所抽象出来的概念无耻容纳。

所以我认为DDD是为了解决上述这些问题的一个好的方法,当然前提是你自己实施过之后才有资格去评判它的优劣,而且是客观公正的。

实施DDD是很费时费力的工程,没有传统的开发方法那么简单快捷,而且对开发人员的整体要求有了一个新的标准,所以本篇文章将介绍一个可以用来替代DDD模式的另外一个比较好的企业模式“活动记录模式”。

2.简单介绍领域模型模式、活动记录模式

领域模型模式其实就是领域驱动设计,两个是一个意思。有兴趣的朋友可以进一步学习领域驱动设计,我认为DDD对于一名企业应用开发人员来说是必不可少的一门设计思想,就好比设计模式一样,它也有着一套模式,用来指导我们进行相关业务场景的设计。

领域模型模式也称领域驱动设计,对业务模型进行等价的面向对象建模,无需太多考虑数据存储的技术细节,但是并不是说完全不考虑如何存储,如果谁告诉你说完全不需要考虑存储那是错误的,因为你要考虑这个领域模型最终是要如何持久化的,以免你将领域模型创建成一个巨大的蜘蛛网。说不需要考虑领域模型如何持久化其实是说你目前只需要把握领域模型创建,不去完成持久化设计细节而已,但是这两个工作往往是互相考虑的。

难道一个不懂得如何存储关系数据的人能够创建出能满足程序员很好的开发的模型吗。

活动记录模式是最靠近DDD的模式,它将数据库中的表中的一行作为自己的对象化字段,然后围绕着这些字段展开的业务逻辑,将数据字段与业务逻辑都封装在一个实例对象中。

活动记录模式与表模块模式不同的是,表模块模式是一个对象对应着一个数据库中的表,而活动记录模式是一个对象对应着一个行记录,所以称为活动记录模式。

此模式最大好处是可以基本上满足业务不是很复杂的情景下,我倒觉得活动记录模式在现在的面向SOA架构下能够更适合企业的业务系统开发团队。使用领域驱动太过于复杂,不使用又会面临着业务快速变化的困境,所以活动记录模式可以考虑试试。

3.活动记录模式的简单示例及要点

我们来看一个简单的示例,了解活动记录模式的开发及要点。

活动记录模式是使用与数据库中的表结构一直的方式使用类的,也就是说表中的列就是类的字段,当然也可以在处理业务逻辑时的辅助字段,尽量不包含多余的字段,这样可以有效保证干净的活动记录。

 1 namespace Business.RecordModels.OrderModel
 2 {
 3     using System;
 4     using System.Collections.Generic;
 5
 6     /// <summary>
 7     /// Order table fields.
 8     /// </summary>
 9     public partial class OrderFields
10     {
11         /// <summary>
12         /// Order id.
13         /// </summary>
14         public long OId { get; set; }
15
16         /// <summary>
17         /// Order name customer declare.
18         /// </summary>
19         public string OName { get; set; }
20
21         /// <summary>
22         /// Product ids.
23         /// </summary>
24         public List<long> PIds { get; set; }
25
26         /// <summary>
27         /// Order sum price.
28         /// </summary>
29         public float Price { get; set; }
30
31         /// <summary>
32         /// Order distribute status.
33         /// </summary>
34         public int DistributeStatus { get; set; }
35
36         /// <summary>
37         /// Order payment status.
38         /// </summary>
39         public int PaymentStatus { get; set; }
40
41         /// <summary>
42         /// Order signer.
43         /// </summary>
44         public string Signer { get; set; }
45
46         /// <summary>
47         /// Submit datetime.
48         /// </summary>
49         public DateTime SubmitDt { get; set; }
50     }
51 } 

定义一个Order活动记录的字段类,也可以直接将该字段定义在Order类中,但是一般我喜欢独立出来,因为字段一旦多了看起来实在很累。如果你想将字段直接定义在Order类中我建议你使用部分类来处理,这样比较干净。

字段中的public List<long> PIds { get; set; } 商品ID集合字段是有意聚合到该字段类中的,因为不管是业务处理还是数据持久化都是需要相关连的业务字段的。  (活动记录模式不要求你很死板的一个表一个记录实例,只要你使用你自己的方式能够让代码结构看上去很自然就是很恰当的。)

虽然你直接使用了int类型来描述业务字段,不过你可以使用其他方式让来该字段在业务处理中不直接使用语言类型而是业务概念。

 1 namespace Business.RecordModels.OrderModel
 2 {
 3     /// <summary>
 4     /// Distribute status const.
 5     /// </summary>
 6     public class DistributeStatusConst
 7     {
 8         public const int NoDistribute = 1;
 9
10         public const int BeginDistribute = 2;
11
12         public const int EndDistribute = 3;
13     }
14 } 

配送状态常量类,定义明确的业务概念的值。

 1 namespace Business.RecordModels.OrderModel
 2 {
 3     /// <summary>
 4     /// Payment status const.
 5     /// </summary>
 6     public class PaymentStatusConst
 7     {
 8         /// <summary>
 9         /// No payment.
10         /// </summary>
11         public const int NoPayment = 1;
12
13         /// <summary>
14         /// End payment.
15         /// </summary>
16         public const int EndPayment = 1;
17     }
18 } 

配送状态常量类,定义明确的业务概念的值。

对活动记录的创建我建议是用工厂来处理,毕竟这里面包含了很多业务逻辑在里面的。

 1 namespace Business.RecordModels.OrderModel
 2 {
 3     using Common;
 4
 5     /// <summary>
 6     /// Order class factory.
 7     /// </summary>
 8     public class OrderFactory
 9     {
10         /// <summary>
11         /// Create a order instance.
12         /// </summary>
13         /// <param name="fields">Order fiels instance.</param>
14         /// <returns>Order instance.</returns>
15         public static Order CreateOrder(OrderFields fields)
16         {
17             if (fields.IsNull() || fields.OName.IsNullOrEmpty()
18                 || fields.PIds.IsNullOrEmpty() || fields.Price.IsLessThanOrEqual0()) return null;
19
20             fields.DistributeStatus = DistributeStatusConst.NoDistribute;//No distribute.
21             fields.PaymentStatus = PaymentStatusConst.NoPayment;//No payment.
22
23             return new Order(fields);
24         }
25     }
26 }

活动记录模式不等于没有DDD那么好,其实在业务相对不是非常复杂的情况下,活动记录模式还是相当不错的,简单快捷,对一些原子类型的字段处理使用常量就很不错。

这里我们使用DistributeStatusConst.NoDistribute、PaymentStatusConst.NoPayment 常量字段来明确的传达业务概念,而不是非要用枚举,经验告诉我有时候枚举没有常量方便。

活动记录对象中包含了该记录所表达的业务逻辑,这里的Order将包含该表所表达的业务逻辑处理。

 1 namespace Business.RecordModels.OrderModel
 2 {
 3     using System;
 4
 5     /// <summary>
 6     /// Order table record
 7     /// </summary>
 8     public partial class Order
 9     {
10         /// <summary>
11         /// Order table columns.
12         /// </summary>
13         private OrderFields fields { get; set; }
14
15         /// <summary>
16         /// New a order instance only internal use.
17         /// </summary>
18         /// <param name="fields">Order fields.</param>
19         internal Order(OrderFields fields)
20         {
21             this.fields = fields;
22         }
23
24         /// <summary>
25         /// Calculate order expiration time.
26         /// </summary>
27         /// <returns>DateTime</returns>
28         public DateTime CalculateExpirationTime()
29         {
30             //Here you can use strategy.
31             if (this.fields.PaymentStatus == PaymentStatusConst.NoPayment)//No payment logic
32             {
33                 return this.fields.SubmitDt.AddDays(1);
34             }
35             else if (this.fields.DistributeStatus == DistributeStatusConst.NoDistribute)//No payment logic
36             {
37                 return this.fields.SubmitDt.AddDays(30);
38             }
39
40             return this.fields.SubmitDt.AddDays(3);
41         }
42     }
43 } 

这里我有一个简单的计算当前订单到期时间的方法(CalculateExpirationTime),在方法内部有一些业务逻辑,而该业务逻辑和当前实例一起存在。

通过使用活动记录模式可以很好的将字段与业务方法有效的集合起来,这样会使得业务逻辑处理比较有条理性,也便于测试和重构。

这里需要强调的是活动记录模式是业务层和数据层共用的模式,当时这里我们所讲的是面向业务层的,也就是说你数据层可以使用任何方式来和活动记录模式整合,现在比较流行ORM了,如果你对性能有要求你可以使用手工处理,建议使用表入口模式来结合,因为数据层没有什么逻辑,如果你的数据层有相关的逻辑我像也不会出现最后的数据源上,而是应该在数据适配层上处理掉,如:缓存、填补字段等。

4.总结

很难在一篇文章中说明所有问题,活动记录模式如果是用在读写分离大的架构中的写端时必须需要“工作单元”模式来协调多“记录”之间的事务性。但是如果你在查询端使用活动记录模式,那么大部分情况下是不需要事务性的,当然查询端我觉得使用事物脚本模式比较直观点,因为业务逻辑也不会有多少。

还是那句话,本篇文章只是分享点自己学习过程中和工作过程总结的经验,仅供参考。其实企业应用架构是一个看似简单其实很复杂的方向,希望与各位一起学习一同进步,谢谢。

 

作者:王清培

出处:http://www.cnblogs.com/wangiqngpei557/

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面

时间: 2024-10-29 00:59:50

.NET应用架构设计—适当使用活动记录模式代替领域模型模式的相关文章

.NET架构设计、框架设计系列文章总结

从事.NET开发到现在已经有七个年头了.慢慢的可能会很少写.NET文章了.不知不觉竟然走了这么多年,热爱.NET热爱c#.突然想对这一路的经历进行一个总结. 是时候开始下一阶段的旅途,希望这些文章可以在发挥点价值作用.     架构设计: ElasticSearch大数据分布式弹性搜索引擎使用 (推荐) DDD实施经验分享-价值导向.从上往下进行(圈内第一个吃螃蟹DDD实施方案)(推荐) 软件工程-思考项目开发那些事(一)(推荐) SOA架构设计经验分享-架构.职责.数据一致性(推荐) .NET

架构设计-业务逻辑层简述

    业务逻辑层是专门处理软件业务需求的一层,处于数据库之上,服务层之下,完成一些列对Domain Object的CRUD,作为一组微服务提供给服务层来组织在暴露给表现层,如库存检查,用法合法性检查,订单创建.    业务逻辑层包含领域对象模型,领域实体,业务规则,验证规则,业务流程.1:领域对象模型为系统结构描述,包含实体功能描述,实体之间的关系.领域模型处于天生的复杂性:2:领域实体:业务层是一些操作业务对象(BO)的处理.业务对象包含数据和行为,是一个完整的业务对象.其不同于上节架构设计

数据源架构模式 表入口 行入口 活动记录 数据映射器

数据源架构模式 - 表入口模式 表入口模式充当数据库表访问入口的对象,一个实例处理表中的所有行. 可以理解为对之前分散在各个页面的sql语句进行封装,一张表就是一个对象,该对象处理所有与该表有关的业务逻辑,很好的提高了代码的复用性. 现在想起来,当初刚毕业那会儿,经常使用表入口模式. 具体的实现方式参见代码: database.php <?php    class Database{       //只是为了演示,通常情况下数据库的配置是会单独写在配置文件中的       private sta

《企业迁云实战》——3.3 应用架构设计

3.3 应用架构设计 上面已经介绍了用户业务上云时如何进行网络设计.运维管理环境规划,本章将重点介绍如何基于阿里云产品和服务设计应用系统架构.3.3.1 负载均衡 阿里云负载均衡(Server Load Balancer,SLB)是将访问流量根据转发策略分发到后端多台ECS的流量分发控制服务.用户可以通过负载均衡的流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性. 阿里云负载均衡主要功能: 负载均衡服务通过设置虚拟服务地址(IP),将多台云服务器ECS实例虚拟成一个高性能

大型网站技术架构之秒杀系统架构设计

秒杀活动的技术挑战 1. 对现有网站业务造成冲击 秒杀活动只是网站营销的一个附加活动,这个活动具有时间短,并发访问量大的特点,如果和网站原有应用部署在一起,必须会对现有业务造成冲击,稍有不慎可能导致整个网站瘫痪. 2. 高并发下的应用.数据库负载 用户在秒杀开始前,通过不停刷新浏览器页面以保证不会错过秒杀,这些请求如果按照一般的网站应用架构,访问应用服务器.连接数据库,会对应用服务器和数据库服务器造成极大的负载压力. 3. 突然增加的网络及服务器带宽 假设商品页面大小200K(主要是商品图片大小

.NET应用架构设计—工作单元模式(摆脱过程式代码的重要思想,代替DDD实现轻量级业务)

阅读目录: 1.背景介绍 2.过程式代码的真正困境 3.工作单元模式的简单示例 4.总结 1.背景介绍 一直都在谈论面向对象开发,但是开发企业应用系统时,使用面向对象开发最大的问题就是在于,多个对象之间的互操作需要涉及数据库操作.两个业务逻辑对象彼此之间需要互相调用,如果之间的互相操作是在一个业务事务范围内的,很容易完成,但是如果本次业务逻辑操作涉及到多个业务对象一起协作完成时问题就来了. 在以往,我们使用过程式的代码(事务脚本模式),将所有与本次业务事务范围内相关的所有逻辑都写在一个大的代码中

如何实现高容量大并发数据库服务 | 数据库分布式架构设计

袋鼠学院和优云.阿里云联合举办的沙龙结束之后,总是有小伙伴们来问PPT内容,想要进一步了解Topic内容.(哦,对了对了,竟然还有小伙伴专门冲着袋鼠云去听沙龙,感动cry~~) 千呼万唤,忙成狗的袋鼠小妹终于把沙龙总结整理了出来(⊙o⊙) 本次沙龙的主题是"云时代下的运维管理实践",受邀请的演讲嘉宾,花名宏翊(经常关注袋鼠云的同学,肯定已经对这个名字很熟悉了),是袋鼠云首席数据库架构师,袋鼠学院数据库讲师. 呼应沙龙运维实践的主题,结合自己的专长领域,宏翊主要是从数据库领域来谈云时代下

Web基础架构设计原则经典论文《架构风格与基于网络的软件架构设计》导读

1. 概述 Roy Fielding博士(见个人主页)是IETF发布的HTTP和URI协议的主要设计者.HTTP和URI是两个最为重要的Web基础技术架构协议,因此Fielding博士可谓是Web架构的奠基者之一. 除了学术上的卓越成就之外,Fielding博士还参与过很多开源软件的设计和开发工作.他是libwww-perl(世界上最早的HTTP开发库之一)的开发者,曾经负责Apache HTTP服务器中与HTTP.URI协议相关部分代码的开发.Fielding博士还指导过很多其他团队在HTTP

IT架构设计框架ADMIT简介

ADMIT(信息技术架构设计(开发)方法学)是一种决策工具,用于系统地开发健壮的系统,它使用了二十种设计驱动力和策略以及十五个方面的生命周期过程.该方法学定义了一个架构的开发生命周期.周期的每个阶段.管理架构开发的流程,可以和其他框架一起使用.另外本文还讨论了架构设计级别和领域.资源维度,以及架构如何与质量和设计相关联. 引言 在信息技术领域,架构在业务现代化.IT转型.软件开发和企业内的其他重要举措等方面发挥了重要作用.使用架构可以为业务问题提供高效.灵活.高质量的技术解决方案.架构可分为三种