.NET应用架构设计—工作单位模式(摆脱程序代码的重要思想,反击DDD)
阅读文件夹:
- 1.背景介绍
- 2.过程式代码的真正困境
- 3.工作单元模式的简单演示样例
- 4.总结
1.背景介绍
一直都在谈论面向对象开发。可是开发企业应用系统时。使用面向对象开发最大的问题就是在于,多个对象之间的互操作须要涉及数据库操作。两个业务逻辑对象彼此之间须要互相调用,假设之间的互相操作是在一个业务事务范围内的,非常easy完毕,可是假设本次业务逻辑操作涉及到多个业务对象一起协作完毕时问题就来了。
在以往,我们使用过程式的代码(事务脚本模式),将全部与本次业务事务范围内相关的全部逻辑都写在一个大的代码中,就算你适当的提取反复代码。效果也不大,由于你永远都摆脱不了夸多个对象互相操作的困境。怎样确认你是否在这个困境中,你仅仅要看你的全部事务操作的入口都仅仅有一个业务方法。
比方当你加入一个订单的时候,你同一时候将订单尾随的商品都一起在“加入订单”的方法中处理的,而不是在另外一个“加入订单商品”的方法中,这两个方法位于不同的表模块类中。
本章将介绍一个模式,此模式专门用来在开发企业应用系统时,协调多个业务对象在一个业务事务范围内,保证一个完整的事务。
2.过程式代码的困境
事实上开发应用系统与开发某个框架或者组件之间的最大差别就是须要考虑数据的持久化,而持久化的逻辑也是和业务逻辑息息相关的,某个方法的最后动作就有可能是加入一行数据或者更新一个字段。而非应用系统的代码往往在最后的时候才去统一刷新终于的持久化文件。并且此类程序非常少存在事务性数据操作。就算有,使用内存事务处理也是比較简单的。不须要考虑那么多的服务端的事情。
我之前也写过非常多组件、框架,尽管谈不上什么复杂的东西,可是给我的经验和感悟就是,怎样将其仔细的设计粒度用在企业应用系统中。怎样进行复杂而仔细的OO设计开发。事实上。假设我们不可以打破过程式代码的格局,那么看再多的OO知识也是心有余而力不足,反而会让你产生非常多负面的情绪(由于我有过这个经历)。
事实上我们还是缺少正确的方法而已。本文中UnitOfWork模式将帮助我们走出过程式的业务逻辑,走向起码的面向对象开发。
有了UnitOfWork你能够任意使用Table module 、Activa Record、Domin Driven 模式,并且你能够依据自己的项目须要将其在大的布局上进行SOA划分(CQRS),让各个模式在各自适合的场景中发挥极致。
3.工作单元模式的简单演示样例
这里我们依旧使用简单的订单购物业务作为演示样例来讲,毕竟大家都懂得这部分的的业务概念。
本实例业务层使用Active Record模式。
namespace OrderManager.Business
{
using System.Collections.Generic; public partial class Order
{
public long OId { get; set; } public List<OrderProducts> Products { get; set; }
}
}
Order活动记录对象的字段部分。
namespace OrderManager.Business
{
public partial class Order
{
public bool CheckOrder()
{
//运行部分业务验证工作
if (this.OId <= 0) return false; return true;
}
}
}
Order活动记录对象主体,纯粹为了演示而用,包括了一个简单的推断业务逻辑。
namespace OrderManager.Business
{
public partial class OrderProducts
{
public long OrderId { get; set; } public long PId { get; set; } public float Price { get; set; }
}
}
订单商品部分字段。
namespace OrderManager.Business
{
public partial class OrderProducts
{
public bool CheckProducts()
{
//运行部分业务验证工作
if (this.OrderId <= 0) return false; return true;
}
}
}
每个商品都包括了自己的逻辑验证。
我们接着看一下应用层入口方法是怎样协调两个活动记录对象之间的业务操作和数据存储的。
namespace OrderManager
{
using OrderManager.Business;
using OrderManager.DataSource; public class OrderManagerController : ControllerBase
{
public bool AddOrder(Order order)
{
using (UnitOfWork unitOfWork = new UnitOfWork())
{
order.CheckOrder();//运行业务检查 order.Products.ForEach(item =>
{
item.CheckProducts();//运行每一个活动记录对象的业务检查。这里也能够使用表模块来处理。
}); OrderGateway orderGateway = new OrderGateway(unitOfWork);
var orderDbResult = orderGateway.AddOrder(order);//第一个数据库表操作 OrderProductsGateway productGateway = new OrderProductsGateway(unitOfWork);
var productDbResult = productGateway.AddOrderProducts(order.Products);//第二个数据库表操作 if (orderDbResult && productDbResult)
{
if (unitOfWork.Commit())
{
this.SendOrderIntegrationMssage(order);//发送成功集成订单消息 return true;
} this.PushOrderProcessQueue(order);//将本次订单发送到处理队列中
return false;
} this.LogBusinessException(order);//记录一个业务处理异常LOG,以备排查问题。 return false;
}
}
}
}
为了简单演示演示样例。我直接使用实例化的方式来构造数据訪问对象,实际使用时能够使用IOC工具来动态注入。
我们接着看一下数据层代码,数据层我使用表入口模式。
namespace OrderManager.DataSource
{
public abstract class GatewayBase
{
protected UnitOfWork UnitOfWork { get; private set; } public GatewayBase(UnitOfWork unit)
{
this.UnitOfWork = unit;
} public bool Commit()
{
return this.UnitOfWork.Commit();
} public void Rollback()
{
this.UnitOfWork.Rollback();
}
}
}
这是一个表入口基类。
namespace OrderManager.DataSource
{
using OrderManager.Business; public class OrderGateway : GatewayBase
{
public OrderGateway(UnitOfWork unit) : base(unit) { } public bool AddOrder(Order order)
{
//这里能够使用你所熟悉的拼接SQL的方式直接操作数据库。而不须要ORM。
return true;
}
}
}
namespace OrderManager.DataSource
{
using OrderManager.Business;
using System.Collections.Generic; public class OrderProductsGateway : GatewayBase
{
public OrderProductsGateway(UnitOfWork unit) : base(unit) { } public bool AddOrderProducts(List<OrderProducts> products)
{
//这里能够使用你所熟悉的拼接SQL的方式直接操作数据库,而不须要ORM。
return true;
}
}
}
这是两个表入口对象,事实上这部分代码是大家都比較熟悉的。所以我这里省略了,你能够直接拼接SQL语句来插入数据库。
namespace OrderManager.DataSource
{
using System; public class UnitOfWork : IDisposable
{
public void Dispose()
{
throw new NotImplementedException();
} public bool Commit()
{
return true;
} public void Rollback()
{
//
}
}
}
UnitOfWrok对象事实上就是对数据库对象的System.Data.Common.DbConnection对象的封装,这里你能够使用你熟悉的方式来构造这个数据库连接对象和开启事务。
事实上值得我们去赞赏的是应用控制器中的代码。在这里非常协调的处理各个逻辑,最后记录下一些必要的日志和发送一些集成消息。你是不是发现你全然能够不使用DDD也能够处理部分业务系统了。
4.总结
活动记录模式+表入口模式+工作单元模式,事实上我认为能够非常好的处理中小型业务逻辑。随着如今SOA化架构,非常少再有多大的项目在一个解决方式里面。
最后还是那句话。提供一个參考资料,假设有兴趣能够进一步交流详细的设计,因为时间关系文章就到这里了,谢谢大家。
作者:王清培
出处:http://blog.csdn.net/wangqingpei557
本文版权归作者和CSDN共同拥有,欢迎转载,但未经作者允许必须保留此段声明,且在文章页面明显位置给出原文连接。否我们保留追究法律责任的权利。
版权声明:本文博主原创文章,博客,未经同意不得转载。
.NET应用架构设计—工作单位模式(摆脱程序代码的重要思想,反击DDD)的更多相关文章
- .NET应用架构设计—工作单元模式(摆脱过程式代码的重要思想,代替DDD实现轻量级业务)
阅读目录: 1.背景介绍 2.过程式代码的真正困境 3.工作单元模式的简单示例 4.总结 1.背景介绍 一直都在谈论面向对象开发,但是开发企业应用系统时,使用面向对象开发最大的问题就是在于,多个对象之 ...
- .NET应用架构设计—表模块模式与事务脚本模式的代码编写
阅读目录: 1.背景介绍 2.简单介绍表模块模式.事务脚本模式 3.正确的编写表模块模式.事务脚本模式的代码 4.总结 1.背景介绍 要想正确的设计系统架构就必须能正确的搞懂每个架构模式的用意,而不是 ...
- 架构设计系列-前端模式的后端(BFF)翻译PhilCalçado
本文翻译自PhilCalçado的官网:https://philcalcado.com/2015/09/18/the_back_end_for_front_end_pattern_bff.html 对 ...
- Unity应用架构设计(1)—— MVVM 模式的设计和实施(Part 2)
MVVM回顾 经过上一篇文章的介绍,相信你对MVVM的设计思想有所了解.MVVM的核心思想就是解耦,View与ViewModel应该感受不到彼此的存在. View只关心怎样渲染,而ViewModel只 ...
- Unity应用架构设计(1)—— MVVM 模式的设计和实施(Part 1)
初识 MVVM 谈起 MVVM 设计模式,可能第一映像你会想到 WPF/Sliverlight,他们提供了的数据绑定(Data Binding),命令(Command)等功能,这让 MVVM 模式得到 ...
- .NET架构设计、框架设计系列文章总结
从事.NET开发到现在已经有七个年头了.慢慢的可能会很少写.NET文章了.不知不觉竟然走了这么多年,热爱.NET热爱c#.突然想对这一路的经历进行一个总结. 是时候开始下一阶段的旅途,希望这些文章可以 ...
- 项目开发中的一些注意事项以及技巧总结 基于Repository模式设计项目架构—你可以参考的项目架构设计 Asp.Net Core中使用RSA加密 EF Core中的多对多映射如何实现? asp.net core下的如何给网站做安全设置 获取服务端https证书 Js异常捕获
项目开发中的一些注意事项以及技巧总结 1.jquery采用ajax向后端请求时,MVC框架并不能返回View的数据,也就是一般我们使用View().PartialView()等,只能返回json以 ...
- [Architecture Design] 跨平台架构设计
[Architecture Design] 跨平台架构设计 跨越平台 Productivity Future Vision 2011 在开始谈跨平台架构设计之前,请大家先看看上面这段影片,影片内容是微 ...
- 大数据时代的IT架构设计
大数据时代的IT架构设计(来自互联网.银行等领域的一线架构师先进经验分享) IT架构设计研究组 编著 ISBN 978-7-121-22605-2 2014年4月出版 定价:49.00元 208页 ...
随机推荐
- hdu2089(数位dp)
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2089 题意:求区间[a,b]内不含有62或4的数的个数. 分析:数位dp,dp[pos][0]表示到第 ...
- hdu4003(树形dp)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4003 题意:给定一棵n个节点的树,遍历每条数边都需要费用cost,现在给定k个机器人,要求用这个k个机 ...
- Linux档案种类与扩展名(2013.09.03)
档案种类: 正规档案(regular file ): 第一个字符为 [ -],例如 [-rwxrwxrwx ].另外,依照档案的内容,又大略可以分为: 纯文本档(ASCII) 二 ...
- Struts2 开发环境搭建
一.开发环境 eclipse+tomcat+struts-2.2.3 eclipse下载地址:http://www.eclipse.org/downloads/ tomca ...
- Android---App Widget(一)
本文译自:http://developer.android.com/guide/topics/appwidgets/index.html App Widgets是一些较小的应用程序窗口,它们能够被嵌入 ...
- U14Linux的帐号与用户组
1.在/etc/group和/etc/gshadow中查找mousegroup: grep mousegroup /etc/group /etc/gshadow (grep的使用) 2.其实Linux ...
- Jetty开发指导:Jetty Websocket API
Jetty WebSocket API使用 Jetty提供了功能更强的WebSocket API,使用一个公共的核心API供WebSockets的服务端和client使用. 他是一个基于WebSock ...
- 【剑指offer】面试题35:第一个数字只出现一次
def FirstNotRepeatingChar(string): hashStr = [0] * 256 for c in string: hashStr[ord(c)] += 1 for c i ...
- iOS随机颜色
#import <UIKit/UIKit.h> @interface UIColor (RandomColor) +(UIColor *) randomColor; @end #impor ...
- Codeforces Round#309 C Kyoya and Colored Balls
给定一个k表示颜色的种类从1到k 然后接下来k行, 每行一个数字, 代表该颜色的球有多少个 这些球都放在一个包中,然后依次拿出. 要求颜色i的最后一个球, 必须要排在颜色i+1的最后一个球前面, ...