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

简介: 阅读目录: 1.背景介绍 2.简单介绍表模块模式、事务脚本模式 3.正确的编写表模块模式、事务脚本模式的代码 4.总结 1.背景介绍 要想正确的设计系统架构就必须能正确的搞懂每个架构模式的用意,而不是胡子眉毛一把抓。

阅读目录:

  • 1.背景介绍
  • 2.简单介绍表模块模式、事务脚本模式
  • 3.正确的编写表模块模式、事务脚本模式的代码
  • 4.总结

1.背景介绍

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

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

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

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

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

表模块模式:

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

事物脚本模式:

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

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

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

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

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

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

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

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属性中)

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:完全独立的过滤无效产品的方法

namespace Business
{
    public class OrderApplicationController
    {
        public void SubmitOrder(Order.OrderField field)
        {
            field.Products = new Product().FilterProduct(field.Products);//先过滤 

            new Order().AddOrder(field);//在添加
        }
    }
}

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

4.总结

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

 

作者:王清培

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

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

目录
相关文章
|
7天前
|
缓存 负载均衡 JavaScript
探索微服务架构下的API网关模式
【10月更文挑战第37天】在微服务架构的海洋中,API网关犹如一座灯塔,指引着服务的航向。它不仅是客户端请求的集散地,更是后端微服务的守门人。本文将深入探讨API网关的设计哲学、核心功能以及它在微服务生态中扮演的角色,同时通过实际代码示例,揭示如何实现一个高效、可靠的API网关。
|
17天前
|
运维 持续交付 开发工具
深入浅出:GitOps在微服务架构中的应用
【10月更文挑战第26天】本文深入探讨了GitOps在微服务架构中的应用,介绍了其核心理念、自动化部署流程和增强的可观测性。通过实例展示了GitOps如何简化服务部署、配置管理和故障恢复,并推荐了一些实用工具和开发技巧。
|
9天前
|
监控 Go API
Go语言在微服务架构中的应用实践
在微服务架构的浪潮中,Go语言以其简洁、高效和并发处理能力脱颖而出,成为构建微服务的理想选择。本文将探讨Go语言在微服务架构中的应用实践,包括Go语言的特性如何适应微服务架构的需求,以及在实际开发中如何利用Go语言的特性来提高服务的性能和可维护性。我们将通过一个具体的案例分析,展示Go语言在微服务开发中的优势,并讨论在实际应用中可能遇到的挑战和解决方案。
|
9天前
|
网络协议 数据挖掘 5G
适用于金融和交易应用的低延迟网络:技术、架构与应用
适用于金融和交易应用的低延迟网络:技术、架构与应用
36 5
|
10天前
|
Go 数据处理 API
Go语言在微服务架构中的应用与优势
本文摘要采用问答形式,以期提供更直接的信息获取方式。 Q1: 为什么选择Go语言进行微服务开发? A1: Go语言的并发模型、简洁的语法和高效的编译速度使其成为微服务架构的理想选择。 Q2: Go语言在微服务架构中有哪些优势? A2: 主要优势包括高性能、高并发处理能力、简洁的代码和强大的标准库。 Q3: 文章将如何展示Go语言在微服务中的应用? A3: 通过对比其他语言和展示Go语言在实际项目中的应用案例,来说明其在微服务架构中的优势。
|
7天前
|
监控 持续交付 Docker
Docker 容器化部署在微服务架构中的应用有哪些?
Docker 容器化部署在微服务架构中的应用有哪些?
|
7天前
|
监控 持续交付 Docker
Docker容器化部署在微服务架构中的应用
Docker容器化部署在微服务架构中的应用
|
9天前
|
开发框架 监控 .NET
【Azure App Service】部署在App Service上的.NET应用内存消耗不能超过2GB的情况分析
x64 dotnet runtime is not installed on the app service by default. Since we had the app service running in x64, it was proxying the request to a 32 bit dotnet process which was throwing an OutOfMemoryException with requests >100MB. It worked on the IaaS servers because we had the x64 runtime install
|
15天前
|
机器学习/深度学习 人工智能 自然语言处理
医疗行业的语音识别技术解析:AI多模态能力平台的应用与架构
AI多模态能力平台通过语音识别技术,实现实时转录医患对话,自动生成结构化数据,提高医疗效率。平台具备强大的环境降噪、语音分离及自然语言处理能力,支持与医院系统无缝集成,广泛应用于门诊记录、多学科会诊和急诊场景,显著提升工作效率和数据准确性。
|
16天前
|
缓存 监控 API
探索微服务架构中的API网关模式
随着微服务架构的兴起,API网关成为管理和服务间交互的关键组件。本文通过在线零售公司的案例,探讨了API网关在路由管理、认证授权、限流缓存、日志监控和协议转换等方面的优势,并详细介绍了使用Kong实现API网关的具体步骤。
36 3