NGuestBook架构体系及实现指南

      前几天我在我的Blog上发布了NGuestBook(点击这里下载),得到了很多反馈,在这里非常感谢大家的关注和支持。一些朋友在E-mail中提到,这个NGuestBook和我那个系列文章《基于.NET平台的分层架构实战》中讲的Demo有非常多不一样的地方,问我能不能单独写一篇文章说明一下这个新NGuestBook的架构方式和实现相关的问题。
      所以我专门写下这篇文章,对这个NGuestBook的架构体系和实现进行一个简要的说明,希望本文的内容能对大家有所帮助。
      有两点要特别说明:一是下面的内容中非正式的使用了UML包图,这里用UML只是为了描述一种架构,而不是建模,所以可能有很多不符合UML标准的地方,还请海涵了,只要您能看懂大体的结构表示就好。二是一下的描述,特别是图示,是以抽象架构工件为基本元素的,可能不会和源码中的工程、文件、类严格对应,但是,应该能很容易分辨出抽象工件元素和具体工程、文件等元素的对应关系。

总体架构
      我们先来看NGuestBook的总体架构图,如图1所示。


图1

      整体采用分层架构,这个思想很明显。从上到下依次为表示层(Web)、业务逻辑层(BusinessComponents)和数据访问层(DataComponents)。
      其中表示层直接依赖业务逻辑层,而业务逻辑层通过数据访问层接口依赖数据访问层。在业务逻辑层和数据访问层接口上,存在依赖注入组件(Factories),便于进行不同数据访问层的替换。
      这里预设了三个数据访问层,LinqDataComponents是使用linq to sql技术为ORM组件实现的数据访问层,SQLDataComponents使用传统的SQL语句访问数据库,这两个数据访问层都是以关系数据库作为数据源;XMLDataComponents是以XML文件为数据源的数据访问层,他们都是DataComponentInterfaces的实现。(特别说明:在提供的源代码中,只实现了LinqDataComponents,其他两个数据访问层只给出了扩展接口,没有具体实现。)
      Entities作为实体类组件,存放系统中用到的“贫血实体类”,这些实体类只用于存放数据,并负责在各层间数据的传递,是各层数据存取传递的媒介和标准。
      Utilities作为工具库组件,存放各种可复用的工具类。
      下面,对各个组件分别进行说明。

实体类组件
      实体类组件是现实世界业务实体在计算机世界中的表示,负责在各层之间的数据的传递,并维护数据格式标准。说通俗一点,就是各个层都“认识”这组标准实体类,传入、传出数据都以这种格式进行。
      为什么要这样呢?因为我们整体思想是尽可能保持各层间的耦合度较低,并相对独立,但是系统要工作,各层间就不可避免交换数据,因此,我们需要一种标准的、简单的、与各层无关的数据格式,否则如果强制某层强制其它层“认识”它特有的数据格式,就可能造成污染。
      例如,如果我们以DataTable为数据交换格式,那么业务逻辑层和表示层都得认识这种数据格式才行,如果有一天,我们要换数据访问层,不需要DataTable了,那么业务逻辑层和表示层都要修改。所以,我们要使用这种标准的、与特定层无关的数据格式作为交换格式,而如果某层有特定的数据格式,要在内部实现转换,对外传递的必须是这种标准格式。
      这里的实体类采用贫血实体类,而且由于业务很简单,整个系统只有一个实体类:MessageInfo。


图2

工具类组件
      工具类组件里是一些可复用的工具性类,这里主要包括三个:
      CacheAccessor:用于缓存的存取操作。
      SessionAccessor:用于Session的存取操作。
      ValidateHelper:用于数据验证的相关操作,主要用在表示层里。


图3

数据访问层接口
      数据访问层接口规定了数据访问层应该实现的方法,并作为业务逻辑层的依赖接口。
      由于整体只有一个实体——Message需要数据持久化,所以数据访问层接口只有一个接口文件。


图4

基于linq to sql的数据访问层
      NGuestBook实现的数据访问层是基于linq to sql的。总体来说,开发小型项目时,linq to sql是不错的ORM解决方案。数据访问层的内部架构如图5所示。


图5

      其中DataClasses是linq to sql框架根据数据库自动生成的特有实体类,用于linq to sql的操作。而数据访问主部件MessageDataComponent仅仅依赖DataClasses,这是因为MessageDataComponent的linq to sql操作必须使用这种特殊的实体类。
      而对外交流时,又需要使用公共实体类MessageInfo,所以,我们需要一个EntityConvertor,作为两种实体类之间的转换器,这个转换器是这个Linq to sql数据访问层的内部机制,对外部一律透明。
      这里要注意,EntityConvertor是一个概念上的工件,实际实现时其功能集成于MessageDataComponent。

业务逻辑层
      业务逻辑层实现主要的业务。这里的业务逻辑层有两个工件:AdminBusinessComponent和MessageBusinessComponent。其中后一个主要实现各种留言的业务操作,而前一个是管理员的业务操作。由于管理员的信息是记录在配置文件中而非持久化在数据库中,所以这个业务工件并不需要数据访问层的支持。
      这里特别提醒,朋友们可以仔细看一下业务逻辑层的方法命名和代码,就会明白,即使在如此微小的系统中,业务逻辑层也不是对数据访问层简单的封装调用,业务逻辑和数据访问是完全两个不同的概念。


图6

依赖注入组件
      依赖注入实现了依赖配置动态选择数据访问层并注入业务逻辑层中,实现两层之间的解耦,具体实现的基础是Abstract Factory模式,并配合了反射机制和缓存机制。


图7

      如图7所示,依赖注入组件的主要工件是DataComponentFactory,它是一个反射工厂,它可以通过反射机制加载某个指定的数据访问层,而后将其注入到业务逻辑层中。至于具体加载哪一个,则依赖Web.config中的配置。
      两外,它还依赖CacheAccessor实现缓存机制,对加载过的数据访问组件进行缓存,提高系统运行效率。

表示层
     NGuestBook的表示层使用了Microsoft ASP.NET MVC框架,版本是Releasse Candidate,所以,整个表示层的架构符合MVC模式。


图8

      由于ASP.NET MVC的架构原理非常复杂,这里就不将具体细节全部表述。大体架构如图8所示,Controllers控制器组件是整个MVC的核心,负责整体的调控。而Views视图组件则使用aspx页面实现,Filters是一些拦截器类,主要实现了身份验证和异常处理的功能。而Controllers直接依赖BusinessComponent完成业务功能,所以BusinessComponent实际上可以看成是MVC的Model。
      实际上,表示层还依赖工具类组件完成Session存取和数据验证的工作。

总结
      以上就是NGuestBook架构的一个简单说明,限于篇幅,不能完全顾及到每一个细节,还请见谅。希望以上内容对大家有所帮助。
      NGuestBook可以这里下载:
     

作者:T2噬菌体
出处:http://leoo2sk.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
1
0
(请您对文章做出评价)
« 上一篇:发布NGuestBook(一个基于.NET平台的分层架构留言本小系统)
» 下一篇:OOA&D实践之路——真实案例解析OO理论与实践(六、迭代式开发与用例驱动)
posted @ 2009-02-25 00:01 EricZhang(T2噬菌体) 阅读(3354) 评论(15)  编辑 收藏 网摘 所属分类: 软件架构

  回复  引用  查看    
#1楼2009-02-25 00:20 | Ryan Gene      
貌似和我现在做的一个小框架架构差不多,区别在于我数据层用了NHibernate,另外还是3层Web, BLL, DAL,只是把DAL抽象了一下,变成IDAL,BLL面对的是IDAL,另外用domain object作为三层的数据契约。

刚开始做不久,等有些成果以后和楼主交流 :)

  回复  引用  查看    
#2楼2009-02-25 01:08 | 灵动生活      
架构比较通用 和我目前的架构很像
  回复  引用  查看    
#3楼2009-02-25 08:12 | 沉默是金      
谢谢楼主分享!!博园需要你这样的人!!!
  回复  引用  查看    
#4楼2009-02-25 08:51 | 艾新      
谢谢楼主分享!不错,不错!能不能把你的源代码发一份到我的邮箱:fjmazhicheng5522@163.com。我这里网速很差,下载不了,谢谢了!
  回复  引用  查看    
#5楼2009-02-25 09:11 | 毁于随      
喜欢PD画的UML,简洁明了.
  回复  引用  查看    
#6楼2009-02-25 09:58 | 张明海      
如何能象校内那样处理海量数据呢?比如现在有100000人同事使用该留言本,谢谢!!!!

  回复  引用  查看    
#7楼2009-02-25 10:39 | GUO Xingwang      
楼主写的文章很实用,而且简单明了,很推荐!
  回复  引用  查看    
#8楼[楼主]2009-02-25 10:42 | T2噬菌体      
@艾新
已发送到你的邮箱

  回复  引用  查看    
#9楼[楼主]2009-02-25 10:46 | T2噬菌体      
@张明海
我对海量数据处理没有经验。
但是根据一些以前看过的东西,处理海量数据关键在于两点:一是分布式架构,二是负载均衡。
因为我不是很懂这些,就不多说了。你可以请教一些这方面的高手或查相关资料。

  回复  引用    
#10楼2009-02-25 10:51 | 杨荣平[未注册用户]
邮件已经收到,特来感谢!!
  回复  引用  查看    
#11楼2009-02-25 11:40 | 小No      
个人觉得你的DataComponentFactory组件实现方式不太好,不够灵活,应该再改进一下

因为:

1. 其实你把所有DataComponent的命名空间都已经在web.config里写死了。
假如我的LinqDataComponent项目下还有其他的文件夹,这时命名空间就不是
NGuestBook.LinqDataComponent,这时我就必须手动修改命名空间

2. 你把所有DataComponent的类名也规定死了,也就是说无论什么DataComponent它的类名都必须是一样的。

我觉得你应该参考一下.NET Provider或者UNITY的实现方式

  回复  引用  查看    
#12楼[楼主]2009-02-25 12:38 | T2噬菌体      
@小No
嗯,这是个问题。如果再灵活一点,可以使用Provider的方式。不过对于一般的项目,使用这种反射方式实现依赖注入,基本够用。如果项目可能会有命名空间的变更和类名的变更,则这种方式就不适用了。

  回复  引用    
#13楼2009-02-26 10:44 | 电脑智能
555……估计楼主使用的是VS2008编译的,偶的2005打不开。

不过细读了文章和代码,真是太感谢楼主,我是新手,虽然还有很多地方不懂。比如抽象工厂的那个模式。还有泛型的应用。不过绝对是一个好文章!

  回复  引用  查看    
#14楼[楼主]2009-02-26 17:55 | T2噬菌体      
@电脑智能
是VS2008环境下开发的,而且还得加装ASP.NET MVC RC扩展包才能打开

  回复  引用  查看    
#15楼2009-06-18 10:54 | 愈圣      
搂主文章很不错,也很实用。谢谢