走向.NET架构设计—第三章—分层设计,初涉架构

简介:
走向.NET 架构设计分层设计,初涉架构(前篇)
  前言:本篇不打算接着上一篇来,这没有关系,以为内他们之间的联系不大,以后我再补上。因为之前一直在谈论设计,也谈了一些TDD 的东西,大家反应觉得讲述的还是有点,所以打算换一种方式:先讲述一些例子,把一些思想穿插着讲述,理论的东西最后最为总结。希望大家支持!
 
本篇主要讲述 ASP.NET 应用中如何进行逻辑分层。本篇的前篇会从 Smart UI  反模式和它的一些缺点开始讲述,然后一步步的讲述如何逻辑分层,而且在后篇中也会给出一个 ASP.NET 设计中常用的仅供参考的分层架构的 Demo
 
 
一个稳定和易维护的系统必须建立在一个好的基础之上。计划和设计一个好的架构对一个项目的成败起着至关重要的作用。可能在我们一般做项目的时候,经验告诉我们:3层,N层的设计,基本就能把问题解决了,很多的情况确实是这样的。在提出一个设计的时候,常常要考虑为什么要这样划分结构,而且常常要承担风险和责任,特别是万一这个项目因为最初的设计而导致崩溃,那就郁闷了。所以设计的提出一定和考虑业务。
 
  下面就先来看看Smart UI的设计方式。
  Smart UI
想想我们最初是如何开发ASP.NET的应用的:在页面设计界面中把界面布局好,然后双击控件就开始编写功能代码。很多的时候把逻辑判断和数据访问都写在页面的.cs的文件中。后来我们学习到了分层,逐渐的明白了这种方式的缺点:导致业务逻辑代码到处分散而且重复,不利于以后的更改和维护等。
 
尽管有上述说的一些缺点,Smart UI还是有它的用途的,如为项目快速的建立一个原型或者开发一个功能比较的小的项目。还有一个问题,如何最初用Smart UI的方式开发的小项目很成功,慢慢的变大,变复杂了,那么很多的问题就出来了。就像Flower在架构模式一书中提到的:尽量用领域模型来组织一个项目的业务逻辑,尽管在开始的时候逻辑不复杂或者看不出这种方式的好处,一旦项目变化,好处就显而易见了。在对项目原型开发中,尽量不用Smart UI
 
其实Smart UI最大的问题就是:职责不清把所有的东西全部写在一起。
为了和以后讲述的内容的比较,我还是写一个例子出来,很多朋友都已经对这种Smart UI的开发方式很熟悉了,可以跳过下面的例子。 
 
这里以产品管理系统中的一个简单场景为例:显示所有的产品信息。例子采用ASP.NET来实现,步骤如下:
     1.创建AgileSharp.Chapter3.AntipatternASP.NET项目,如图 所示:
 
     2.  选择App_Data文件夹,添加数据库OrderManagement.mdf,如图 所示 
 
 
 
 
3. 在新加的数据库文件上右击,并且打开。然后添加一个新表:如下:
 
 
其中ProductId设置为自动标示。
然后保存为Products表。
 
4. 添加一些测试的数据. 
     5. 然后选择Products表,并且把表拖放到Default.aspx页面上。这样之后,在页面上就自动添加一个GridViewSqlDataSource.
 
界面就如下图:
 
6. 我我们添加额外的两列来显示折扣信息和库存信息。
 
7. 然后,我们在Default.aspx.cs后编码:
 
protected void gvProduct_RowDataBound(object sender,GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
        {
        intproductId = int.Parse(((System.Data.DataRowView)e.Row.DataItem)
        [“ProductId”].ToString());

        decimal price = decimal.Parse(((System.Data.DataRowView)e.Row.DataItem)
            [“Price”].ToString());

            Label lblDiscount = (Label)e.Row.FindControl(“lblDiscount”);

        lblDiscount.Text = DisplayDiscount
    (ApplyDiscountsStrategy(productId, price));

       }
}
        
在上面的 GridView1_RowDataBound方法在GridView的每个row被创建的时候调用。这个方法获取每个产品的推荐的零售价格RRP(Recommend Retail Price),然后调用 DisplayDiscountDisplaySavings方法来获取折扣和库存,然后再更新UI的显示。
         在上面的代码中,就将计算折扣和计算库存的逻辑写在了UI中,而且数据的访问代码也写在UI中了。这就意味着:如果我们想要在不同的页面显示产品的信息,那么这些逻辑就得一遍遍的重写。如果我们在加一些新的功能,那么页面后面的代码就开始修改,开始缝缝补补。
 
  解决Smart UI的方法就是划分职责,我想大家都知道“单一职责的原则”,这个原则不仅仅适用于类,方法,而且对项目的层次划分也有作用。分层,最主要的目的就是:把不通的功能放在各自对应的地方,这样清晰的职责划分,也是对变化点进行分离。
  下面的图就是一个典型的企业级ASP.NET项目的分层结构:
 
  下面我们就来看看,按照我们的一般的分层的经验来如何设计这功能:
     下面,我们再次来练下手,重新设计前面提到的订单管理系统,使其功能适应新的需求(很多时候,重新设计基本不可能的,所以在开始设计时就需要考虑清楚,这里重新设计只是从举例的角度来考虑的):
(1) 支持用户通过网页或PC桌面程序来访问系统。
(2) 订单管理系统需要为其他的系统(如财务系统等)提供服务。
(3) 订单的一些处理流程和相关的业务处理在其他的系统要用到。
(4) 还有更多的需求,等待确认。
 
  注:朋友们一眼就应该可以看出,这些类库的命名是反映了一些DDD的一些概念,但是,不是说在一个项目的开发中用了这些概念名词就表明就开发的方式是DDD了。
 
  这里我先提一下上面类库的一起名字:尽管有关DDD和一些架构模式的概念我在以后的文章中会讲,但我这里还是先给大家提一下,目的仅仅是让大家对这个例子有一些更好的了解。
  在DDD中,一直主张业务模型,也就是我们常常所说的业务类,例如之前例子中的Product,只关注自身的业务逻辑,而不管如何去获取和保存数据,这些对数据的操作完全交给另外的对象去执行,也就是Repository,这样就达到了DDD中所说的PIPersistence Ignore)。所以在上面的例子中,ASPPatterns.Chap3.Layered.Model就代表了一个业务模型,它之所以被Repository引用,是因为Repository负责将Model的数据持久化到存储设备中,而Model不管这些事情了。
 
  在讲之前,首先给大家统一 一下Service的概念。 
  有时在类的设计过程中,有些行为不适合放在任何的一个类中,如果把这些行为放在一个不真正拥有它的类中,只能把类的职责搞混了。为了给这些行为一个安置的地方,我们常常把这些行为放在一个称为服务的类中。
 
  作为服务的类一般没有状态的,可以简单的作为一个提供操作接口实现。
  在DDD中,Service也是用来提供一种服务的。很多人看到了DDD的类层次结构是这样的:Repository---Model---Service--- Presentation(包括本例),所以都以为Service只能出现在Model的上一层,如果看到Repository-- Service ---Model---Service--- Presentation这样的层次结构,又作何感想。如果被这些所谓的结构搞迷惑了,那就说明对DDD的理解只是在于“形”上。Service就是向外部提供的功能接口,和我们常见的Web Service的概念很相似,例如的Web Service就是向外部系统提供一些功能的。
  我们来看下面的一个图:
 
 
 
  有时候之所以要在Model层之上加上一个Service层,主要的原因就是实现粗颗粒度的API,往往和系统的User Case有一定的联系。例如,如果在系统用例中要实现一个用户订单的处理,那么可能就涉及到Customer, Product,Order等类,当然,如果我们调用这些类来共同完成这个任务是没问题的,但是这样就向调用者暴露这些类之间的复杂的关系,而且如果处理的过程变化了,那么调用者的代码就要改变,如果把这个处理的方法放在上面的任意一个类中,又显得不伦不类,这里的Service功能就类似于设计模式中的Façade外观模式。这样就向外界提供简单的API,向外界提供订单处理的服务!
 
  所以在一般在DDD中业务层被划分为两个逻辑层:Model (提供细粒度的业务逻辑处理,也便于重用), Service(提供业务处理的流程,提供粗颗粒度的供外部调用的方法)。
 
  但是,我们常见到的Model层之上的Service层仅仅只是对CRUD的再次封装,一个可能的原因就是业务不是很复杂,这时其实这个Service层可以拿掉的,但是考虑到以后可能逻辑会更多更复杂,所以还是保留Service这层。
 
  其实在Repository上的那个Service也是同样的概念。例如发送邮件通知用户的功能。例如上图中的最上层的Service可以调用业务层和基础设施层的Service来共同完成一个事情。
 
  今天的上篇的就讲述到这里吧,下篇会用一个例子,代码量还是有点的!敬请关注!
  大家感兴趣,我们下篇讲述!























本文转自yanyangtian51CTO博客,原文链接:
http://blog.51cto.com/yanyangtian/410222
 ,如需转载请自行联系原作者


相关文章
|
2月前
|
负载均衡 关系型数据库 应用服务中间件
高可用系列文章之二 - 传统分层架构技术方案
高可用系列文章之二 - 传统分层架构技术方案
|
29天前
|
数据安全/隐私保护 Windows
.net三层架构开发步骤
.net三层架构开发步骤
9 0
|
29天前
深入.net平台的分层开发
深入.net平台的分层开发
46 0
|
1月前
|
分布式计算 API 数据处理
Flink【基础知识 01】(简介+核心架构+分层API+集群架构+应用场景+特点优势)(一篇即可大概了解flink)
【2月更文挑战第15天】Flink【基础知识 01】(简介+核心架构+分层API+集群架构+应用场景+特点优势)(一篇即可大概了解flink)
56 1
|
2月前
|
存储 自然语言处理 前端开发
软考实践之分层架构思想的理论和应用实践
软考实践之分层架构思想的理论和应用实践
217 0
|
2月前
|
消息中间件 前端开发 测试技术
DDD - 分层架构:有效降低层与层之间的依赖
DDD - 分层架构:有效降低层与层之间的依赖
|
3月前
|
XML Dubbo Java
【面试问题】Dubbo 的整体架构设计有哪些分层?
【1月更文挑战第27天】【面试问题】Dubbo 的整体架构设计有哪些分层?
|
10天前
|
API 数据库 开发者
构建高效可靠的微服务架构:后端开发的新范式
【4月更文挑战第8天】 随着现代软件开发的复杂性日益增加,传统的单体应用架构面临着可扩展性、维护性和敏捷性的挑战。为了解决这些问题,微服务架构应运而生,并迅速成为后端开发领域的一股清流。本文将深入探讨微服务架构的设计原则、实施策略及其带来的优势与挑战,为后端开发者提供一种全新视角,以实现更加灵活、高效和稳定的系统构建。
18 0
|
24天前
|
负载均衡 测试技术 持续交付
高效后端开发实践:构建可扩展的微服务架构
在当今快速发展的互联网时代,后端开发扮演着至关重要的角色。本文将重点探讨如何构建可扩展的微服务架构,以及在后端开发中提高效率的一些实践方法。通过合理的架构设计和技术选型,我们可以更好地应对日益复杂的业务需求,实现高效可靠的后端系统。
|
8天前
|
Kubernetes 安全 Java
构建高效微服务架构:从理论到实践
【4月更文挑战第9天】 在当今快速迭代与竞争激烈的软件市场中,微服务架构以其灵活性、可扩展性及容错性,成为众多企业转型的首选。本文将深入探讨如何从零开始构建一个高效的微服务系统,覆盖从概念理解、设计原则、技术选型到部署维护的各个阶段。通过实际案例分析与最佳实践分享,旨在为后端工程师提供一套全面的微服务构建指南,帮助读者在面对复杂系统设计时能够做出明智的决策,并提升系统的可靠性与维护效率。

热门文章

最新文章