.NET应用架构设计—表模块模式与事务脚本模式的代码编写

简介:

阅读目录:

  • 1.背景介绍

  • 2.简单介绍表模块模式、事务脚本模式

  • 3.正确的编写表模块模式、事务脚本模式的代码

  • 4.总结

1.背景介绍

要想正确的设计系统架构就必须能正确的搞懂每个架构模式的用意,而不是胡子眉毛一把抓。现在有一个现象是什么呢,项目的结构从表面上看是很不错,层分的很合理,其实对业务系统来说也就那么几种层设计方法,但是现在很多项目的逻辑架构的设计不是理想,有很多概念大家并不是很了解,当然也许每个人对技术的追求不同罢了。不管你追求不追求,事实我们还是要去往正确的方向努力才对的。

很多人包括我自己在内,都是写过很多年的过程式的代码,层对我当年来说就是个摆设而已,最典型的问题就是我们总是将表模块模式和事物脚本模式一起混着使用,什么意思呢,就是说我们都会使用一些代码生成器来根据数据库中的表来生成三层架构中的业务层和数据层,有些比较好的代码生成器也可以帮你把UI层中的部分视图也生成好,确实很强大,有些场合下这是一中最合适的过程。

但是现在的系统已经不在是那样的了,其中重要的一点就是业务复杂了,如果我们还稀里糊涂的编写着代码,最后只会成为你或者团队的技术债务。

2.简单介绍表模块模式、事务脚本模式

我们简单了解一下这里所谓的“表模块模式、”事务脚本模式“到底是什么样子的模式,最关键是你也许就知道了你目前所使用的业务层架构风格是什么模式,强调一下“表模块模式”、“事物脚本模式”都是业务层的构架模式。

表模块模式:

简单讲就是你数据库中的每个表对应着业务层中的一个对象定义,如果你有一个Product表,那么你在Business Layer中就有一个Product.cs文件,当然这不是绝对的,你也可以将库中的视图也定义一个类型,如,OrderProduct.cs,也是可以的。然后每个类中的所处理的逻辑都是跟这张表相关的,你在Product.cs中的代码就不要包含Order.cs中的代码了。目前来看是有的,因为现在大部分的项目都是在写着使用过程式的代码,也就是事物脚本模式,这样难免会将其他类型中的代码写到本类中。

事物脚本模式:

事务脚本模式就是过程式的代码,只不过它的指标就是每一个代码段独立完成一个业务单元,而不是到处都是过程代码,事物脚本模式还是很强调逻辑的统一性的。

使用此模式进行写代码时,你就不要单纯的使用数据库中的表名来定义业务类了,因为你是使用事务脚本模式的,你需要站在业务角度来规划你的业务层中大概包含哪些业务概念,然后使用这个业务概念来命名你的类。比如:UserOrder,UserOrder,类似这样的定义,当然这里只是个假设而已,你不要站在数据库的脚本来设计业务层就行了,这样你就起码不会使用到很细粒度的类型,哪怕下一次迭代进行重构也是可以的。

3.正确的编写表模块模式、事务脚本模式的代码

这篇文章的重点就是本节,我们将了解一下这两种模式的代码到底该如何编写。

说代码如何编写似乎有点让人觉得不是很礼貌,其实我们大部分的代码写的都是正确的,但是如果我们将有些代码稍微的罗一下位置就会明显不一样。

我们来看一个小例子,例子很简单,有两个类型Order、Product,用来完成一般的业务逻辑处理,我们通过不同的模式来看到底如何使用。

现在的事务脚本模式的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
namespace  Business
{
     public  class  Order
     {
         [Serializable]
         public  class  OrderField
         {
             public  string  OId {  get set ; }
[NonSerialized]
             public 
List<Product.ProductField> Products {  get set ; }
         }
public  OrderField Field {  get set ; }
public  void  AddOrder(OrderField orderField)
         {
             var  sendMQOrders =  new  List< string >(); //合格的产品ID集合
orderField.Products.ForEach(product =>
             {
                 if  (product.Price <= 20) //不满足条件
                     return ;
sendMQOrders.Add(product.PId); //满足条件
             });
MqHelper.SendOrder(orderField, 
sendMQOrders); //发送订单数据实体到队列中
         }
     }
}

Order业务类中有一个添加Order的方法,在该方法中是一些简单的业务逻辑处理,判断了要添加的这个商品的价格是否大于20块钱。最后使用过滤下来的商品ID作为本订单的有效产品。

这就是我们目前使用的代码风格,这里有两个问题,第一:类的命名,Order的概念太大了,没有进行细化,显然不是按照事务脚本模式来进行设计的而是按照表模块方式进行划分的,还有如果我就算你是按照事物脚本模式来设计的,我就喜欢定义大的概念难道不对吗?也可以,但是在Order的定义里面明确使用了Product类型下的子类型,也就说这里出现了两个独立的业务范围,正常的理解肯定是按照表模块模式来设计的。第二:如果是按照表模块模式来设计的,因为根据这个对象的命名很明显是此模式,但是仔细阅读一下代码发现职责还是有点不清晰,在Order.AddOrder(OrderField orderField)方法中,有Product的逻辑在里面if (product.Price <= 20),当然这里是业务逻辑比较简单的情况下的,如果是业务比较复杂的时候,就会出现大量的代码在Order类中,到最后就会发现我们已经分不清此业务架构到底是使用何种模式来设计的。

我们有两个做法,第一个做法是:将其改成事务脚本模式,让类的命名和设计泛化,也就是说不要定义那么明显的数据库中的表名字,不要清晰的区分Order和Product两个职责。第二个做法是:将其改成表模块模式,将每个类型中的业务逻辑完全清晰化,将if (product.Price <= 20)提取到Product业务类中去,然后在应用控制器中先处理此逻辑后在调用Order.AddOrder(OrderField orderField)方法进行处理,这个方法里面只做跟当前类型相关的逻辑,参考的依据就是一旦你发现你所写的代码里出现了别的类型时,此时你应该告诉自己有可能这个地方需要重构职责。

两个方法来移动此逻辑:

1:(将if (product.Price <= 20)封进Price属性中)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
namespace  Business
{
     public  class  Order
     {
         [Serializable]
         public  class  OrderField
         {
             public  string  OId {  get set ; }
[NonSerialized]
             public 
List<Product.ProductField> Products {  get set ; }
         }
public  OrderField Field {  get set ; }
public  void  AddOrder(OrderField orderField)
         {
             var  sendMQOrders =  new  List< string >(); //合格的产品ID集合
orderField.Products.ForEach(product =>
             {
                 if  (product.Price.IsValid() /*执行价格判断*/ return ;
sendMQOrders.Add(product.PId); //满足条件
             });
MqHelper.SendOrder(orderField, 
sendMQOrders); //发送订单数据实体到队列中
         }
     }
}

此方法有个问题就是商品的价格没有收到订单的控制,这看具体的业务需要了,我只是个假设。

2:完全独立的过滤无效产品的方法

1
2
3
4
5
6
7
8
9
10
11
12
namespace  Business
{
     public  class  OrderApplicationController
     {
         public  void  SubmitOrder(Order.OrderField field)
         {
             field.Products =  new 
Product().FilterProduct(field.Products); //先过滤
new  Order().AddOrder(field); //在添加
         }
     }
}

我们先调用Product中的业务方法过滤无效的商品,然后在进行订单添加操作,这样我们就将各自的职责放到自己的位置去。

4.总结

还是那句话,这只是我学习过程中的一点小小的领悟,给大家一个参考的资料,希望对你有用,谢谢。




 本文转自 王清培 51CTO博客,原文链接: http://blog.51cto.com/wangqingpei557/1544906,如需转载请自行联系原作者


相关文章
|
20天前
|
运维 持续交付 开发工具
深入浅出:GitOps在微服务架构中的应用
【10月更文挑战第26天】本文深入探讨了GitOps在微服务架构中的应用,介绍了其核心理念、自动化部署流程和增强的可观测性。通过实例展示了GitOps如何简化服务部署、配置管理和故障恢复,并推荐了一些实用工具和开发技巧。
|
11天前
|
监控 Go API
Go语言在微服务架构中的应用实践
在微服务架构的浪潮中,Go语言以其简洁、高效和并发处理能力脱颖而出,成为构建微服务的理想选择。本文将探讨Go语言在微服务架构中的应用实践,包括Go语言的特性如何适应微服务架构的需求,以及在实际开发中如何利用Go语言的特性来提高服务的性能和可维护性。我们将通过一个具体的案例分析,展示Go语言在微服务开发中的优势,并讨论在实际应用中可能遇到的挑战和解决方案。
|
11天前
|
网络协议 数据挖掘 5G
适用于金融和交易应用的低延迟网络:技术、架构与应用
适用于金融和交易应用的低延迟网络:技术、架构与应用
39 5
|
12天前
|
Go 数据处理 API
Go语言在微服务架构中的应用与优势
本文摘要采用问答形式,以期提供更直接的信息获取方式。 Q1: 为什么选择Go语言进行微服务开发? A1: Go语言的并发模型、简洁的语法和高效的编译速度使其成为微服务架构的理想选择。 Q2: Go语言在微服务架构中有哪些优势? A2: 主要优势包括高性能、高并发处理能力、简洁的代码和强大的标准库。 Q3: 文章将如何展示Go语言在微服务中的应用? A3: 通过对比其他语言和展示Go语言在实际项目中的应用案例,来说明其在微服务架构中的优势。
|
10天前
|
监控 持续交付 Docker
Docker 容器化部署在微服务架构中的应用有哪些?
Docker 容器化部署在微服务架构中的应用有哪些?
|
10天前
|
监控 持续交付 Docker
Docker容器化部署在微服务架构中的应用
Docker容器化部署在微服务架构中的应用
|
18天前
|
机器学习/深度学习 人工智能 自然语言处理
医疗行业的语音识别技术解析:AI多模态能力平台的应用与架构
AI多模态能力平台通过语音识别技术,实现实时转录医患对话,自动生成结构化数据,提高医疗效率。平台具备强大的环境降噪、语音分离及自然语言处理能力,支持与医院系统无缝集成,广泛应用于门诊记录、多学科会诊和急诊场景,显著提升工作效率和数据准确性。
|
18天前
|
JavaScript 持续交付 Docker
解锁新技能:Docker容器化部署在微服务架构中的应用
【10月更文挑战第29天】在数字化转型中,微服务架构因灵活性和可扩展性成为企业首选。Docker容器化技术为微服务的部署和管理带来革命性变化。本文探讨Docker在微服务架构中的应用,包括隔离性、可移植性、扩展性、版本控制等方面,并提供代码示例。
54 1
|
20天前
|
运维 Serverless 数据处理
Serverless架构通过提供更快的研发交付速度、降低成本、简化运维、优化资源利用、提供自动扩展能力、支持实时数据处理和快速原型开发等优势,为图像处理等计算密集型应用提供了一个高效、灵活且成本效益高的解决方案。
Serverless架构通过提供更快的研发交付速度、降低成本、简化运维、优化资源利用、提供自动扩展能力、支持实时数据处理和快速原型开发等优势,为图像处理等计算密集型应用提供了一个高效、灵活且成本效益高的解决方案。
58 1
|
23天前
|
前端开发 API UED
深入理解微前端架构:构建灵活、高效的前端应用
【10月更文挑战第23天】微前端架构是一种将前端应用分解为多个小型、独立、可复用的服务的方法。每个服务独立开发和部署,但共同提供一致的用户体验。本文探讨了微前端架构的核心概念、优势及实施方法,包括定义服务边界、建立通信机制、共享UI组件库和版本控制等。通过实际案例和职业心得,帮助读者更好地理解和应用微前端架构。
下一篇
无影云桌面