走向.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.Antipattern的ASP.NET项目,如图 所示:
 
     2.  选择“App_Data”文件夹,添加数据库“OrderManagement.mdf”,如图 所示 :
 

 
 
 
3. 在新加的数据库文件上右击,并且打开。然后添加一个新表:如下:
 
 
其中ProductId设置为自动标示。
然后保存为Products表。
 
4. 添加一些测试的数据. 
     5. 然后选择Products表,并且把表拖放到Default.aspx页面上。这样之后,在页面上就自动添加一个GridView和SqlDataSource.

 
界面就如下图:
 

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),然后调用 DisplayDiscount和DisplaySavings方法来获取折扣和库存,然后再更新UI的显示。
         在上面的代码中,就将计算折扣和计算库存的逻辑写在了UI中,而且数据的访问代码也写在UI中了。这就意味着:如果我们想要在不同的页面显示产品的信息,那么这些逻辑就得一遍遍的重写。如果我们在加一些新的功能,那么页面后面的代码就开始修改,开始缝缝补补。
 
  解决Smart UI的方法就是划分职责,我想大家都知道“单一职责的原则”,这个原则不仅仅适用于类,方法,而且对项目的层次划分也有作用。分层,最主要的目的就是:把不通的功能放在各自对应的地方,这样清晰的职责划分,也是对变化点进行分离。
  下面的图就是一个典型的企业级ASP.NET项目的分层结构:
 
  下面我们就来看看,按照我们的一般的分层的经验来如何设计这功能:
     下面,我们再次来练下手,重新设计前面提到的订单管理系统,使其功能适应新的需求(很多时候,重新设计基本不可能的,所以在开始设计时就需要考虑清楚,这里重新设计只是从举例的角度来考虑的):
(1) 支持用户通过网页或PC桌面程序来访问系统。
(2) 订单管理系统需要为其他的系统(如财务系统等)提供服务。
(3) 订单的一些处理流程和相关的业务处理在其他的系统要用到。
(4) 还有更多的需求,等待确认。
 
  注:朋友们一眼就应该可以看出,这些类库的命名是反映了一些DDD的一些概念,但是,不是说在一个项目的开发中用了这些概念名词就表明就开发的方式是DDD了。
 
  这里我先提一下上面类库的一起名字:尽管有关DDD和一些架构模式的概念我在以后的文章中会讲,但我这里还是先给大家提一下,目的仅仅是让大家对这个例子有一些更好的了解。
  在DDD中,一直主张业务模型,也就是我们常常所说的业务类,例如之前例子中的Product,只关注自身的业务逻辑,而不管如何去获取和保存数据,这些对数据的操作完全交给另外的对象去执行,也就是Repository,这样就达到了DDD中所说的PI(Persistence 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来共同完成一个事情。
 
  今天的上篇的就讲述到这里吧,下篇会用一个例子,代码量还是有点的!敬请关注!
  大家感兴趣,我们下篇讲述!

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

  1. 走向.NET架构设计—第三章—分层设计,初涉架构(后篇)

    走向.NET架构设计-第三章-分层设计,初涉架构(后篇) 前言:本篇主要是接着前两篇文章继续讲述! 本篇的议题如下: 4. 数据访问层设计 5. 显示层设计 6. UI层设计   4.  数据访问层设 ...

  2. 《大型网站技术架构》——第三章 大型网站核心架构要素

    系统的各个重要组成部分及其关系构成了系统的架构. 系统功能 性能 响应 很多时候网站性能问题是网站架构升级优化的触发器. 浏览器端:浏览器缓存.页面压缩.合理布局页面.减少Cookie传输 CDN:将 ...

  3. 走向ASP.NET架构设计-第六章-服务层设计(中篇)

    走向ASP.NET架构设计-第六章-服务层设计(中篇) 前言:上一篇文章介绍了一些服务层的基本知识,而且也简要的介绍了SOA的有关知识,本篇主要是介绍在服务层可以采用的一些模式.  本篇议题如下: F ...

  4. 第三章 区块链技术架构与发展趋势

    第三章 区块链技术架构与发展趋势 整个区块链与密码学大体内容介绍安排如下: https://blog.csdn.net/qq_43479839/article/details/114630163 参考 ...

  5. 架构漫谈(三):如何做好架构之识别问题

    2019独角兽企业重金招聘Python工程师标准>>> 架构漫谈(三):如何做好架构之识别问题 作者: 王概凯  来源: InfoQ  发布时间: 2016-04-17 10:47  ...

  6. 软考-架构师-第三章-数据库系统 第八节 数据库设计的基本步骤(读书笔记)

    版权声明 主要针对希赛出版的架构师考试教程<系统架构设计师教程(第4版)>,作者"希赛教育软考学院".完成相关的读书笔记以便后期自查,仅供个人学习使用,不得用于任何商业 ...

  7. 软考-架构师-第三章-数据库系统 第七节 数据库设计(读书笔记)

    版权声明 主要针对希赛出版的架构师考试教程<系统架构设计师教程(第4版)>,作者"希赛教育软考学院".完成相关的读书笔记以便后期自查,仅供个人学习使用,不得用于任何商业 ...

  8. 《软件工程》第三章——软件设计综述

    1. 软件设计的任务与目标 任务和目标:以软件需求规格设计说明书为依据,根据其提出的系统目标,进行数据设 计(数据结构),系统结构设计(软件系统的体系结构),过程设计(吧结构转换为软件的过程性描述), ...

  9. 软考高级-系统架构师-第五章软件架构设计

    本篇博文目录: 一.软件架构设计 1.软件架构的定义 2.体系结构设计(SA)与生命周期 (1) 需求分析阶段 (2) 设计阶段 (3) 实现阶段 (4) 构建组装阶段 (5) 部署阶段 (6) 后开 ...

最新文章

  1. 如何合理的学习Netty?(学习目录)
  2. 【Xamarin开发 Android 系列 4】 Android 基础知识
  3. linux下makefile
  4. 工具——Java后端开发中用到的一些工具(windows)
  5. 什么是分布式锁及正确使用redis实现分布式锁
  6. PXC5.7(Percona XtraDB Cluster)+HAproxy集群部署
  7. x5内核有什么优点_接上U盘就是NAS私有云,蒲公英X5入手测评
  8. 2016校招真题编程练习——微信红包(腾讯)
  9. 如果没有英语,计算机,如果有一天没有电脑(英语作文)
  10. 21天学通python-21天学通python
  11. DHCP详细工作过程(转)
  12. 基于PHP的新闻管理系统(基础版)
  13. 计算机体系结构课后答案
  14. 优盘中发现计算机病毒怎么办,u盘插电脑中了病毒怎么办
  15. Ubuntu 永久修改DNS
  16. 华为openEuler(EulerOS)系统 设置yum源
  17. Latex中在字母上加上波浪线
  18. SparkCore核心机制详解
  19. 抛物线交点式公式_抛物线所有公式
  20. 【ECM技术】ECM(Enhanced Compression Model)帧间技术总结

热门文章

  1. 在Nginx上配置多个站点
  2. Javascript获取Html界面元素的几种方法
  3. Visual Studio服务器控件被警告问题
  4. Django Localization 之language file
  5. linux 脚本详解,shell脚本分析日志
  6. Flask发送邮件,最基础
  7. Python 懂车帝全系车型--参数分析
  8. win10安装tesserocr配置 Python使用tesserocr识别字母数字验证码
  9. 微信进行证书相关操作(退款,发放优惠券等)时报System.Security.Cryptography.CryptographicException: 出现了内部错误。...
  10. JS中Node节点总结