架构设计基本原则
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
数据访问层的一种实现:Access+SQL
通过前面的工作,整个系统的框架算是基本搭 建完了,下面,我们要具体实现各个层次。关 于数据访问层的实现,我们讨论三种实现方式 ,第一种:Access+动态生成SQL。 顾名思义,这种实现将使用Access作为后台数 据库,而操作方式也是最基本的使用SQL命令。 在具体编写实现代码之前,我们需要做一些准 备工作:
其中第一个原则,保证了依赖的逐层性,及整个架构 的依赖是逐层向下的,而不能跨层依赖。第二个原则 ,则保证了依赖的单向性,及只能上层依赖底层,而 不能底层反过来依赖上层。
针对接口编程,而不是针对实现编程
这里所指的接口,不是特指编程语言中的具体语言元素(如C#中 由Interface定义的语言接口),而是指一种抽象的,在语义层 面上起着接合作用语义体。它的具体实现,可能是接口,可能是 抽象类,甚至可能是具体类。 从不同的视角,接口可以有以下两种定义: 1.接口是一组规则的集合,它规定了实现本接口的类或接口 必须拥有的一组规则。体现了自然界“如果你是……则必须能 ……”的理念。 2.接口是在一定粒度视图上同类事物的抽象表示。注意这里 我强调了在一定粒度视图上,因为“同类事物”这个概念是相对 的,它因为粒度视图不同而不同。 具体到N层架构中,针对接口编程的意义在部分上是这样的: 现仍约定将N层架构的各层依次编号为1、2、…、K、…、N1、N,其中层的编号越大,则越处在上层,那么第K层不应该依 赖具体一个K-1层,而应该依赖一个K-1层的接口,即在第K层中 不应该有K-1层中的某个具体类。
系统的工程结构
在初始阶段,整个系统包括6个工程,它们的职责是这 样的: Web——表示层 Entity——存放实体类 Factory——存放和依赖注入及IoC相关的类 IBLL——存放业务逻辑层接口族 IDAL——存放数据访问层接口族 Utility——存放各种工具类及辅助类 这只是一个初期架构,主要是将整个系统搭一个 框架,在后续开发中,将会有其他工程被陆陆续续添 加进来。 实体类将放在Entity工程下
模块划分及交互设计
实体类模块:一组实体类的集合,负责整个系统中数据的封装及传递。
数据访问层接口族:一组接口的集合,表示数据访问层的接口。
业务逻辑层接口族:一组接口的集合,表示业务逻辑层的接口。 数据访问层模块:一组类的集合,完成数据访问层的具体功能,实现数 据访问层接口族。 业务逻辑层模块:一组类的集合,完成业务逻辑层的具体功能,实现业 务逻辑层接口族。
1.建立工程 在这个架构中,业务逻辑层是可以 替换的。及业务逻辑层不是直接耦合于 表示层,而是通过依赖注入机制实现。 所以,我们这里将这个业务逻辑层不直 接命名为BLL,而是新建一个叫 SimpleBLL的工程,放置我们这个业务逻 辑层的相关代码。
2.实现具体的数据访问操作类 因为前面已经定义了数据访问层接口 ,所以实现数据访问操作类就是很机械 的工作了。 这里主要包括三种类型的操作,一种 是修改型,如Insert;一种是返回单个 实体类型,如GetByID;还有一种是返回 实体类集合型,如GetAll。
依赖注入机制及IoC的设计与实现
依赖倒置原则
在软件设计原则中,有一种重要的思想叫做依赖倒置 。它的核心思想是:不能让高层组件依赖底层组件, 而且,不管高层组件和底层组件,两者都应依赖于抽 象。 那么,这个原则和我们上面的原则是否矛盾呢? 其实并不矛盾。 因为这个原则定义中的“依赖”是指“具体依赖 ”,而上面定义中的依赖全部指“抽象依赖”。我对 这两种依赖的定义如下: 具体依赖——如果P层中有一个或一个以上的地方 实例化了Q层中某个具体类,则说P层具体依赖于Q层。 抽象依赖——如果P层没有实例化Q层中的具体类 ,而是在一个或一个以上的地方实例化了Q层中某个接 口,则说P层抽象依赖于Q层,也叫接口依赖于Q层。
业务逻辑层的实现
在实际应用中,业务逻辑层是至关重要 的,他承载着整个系统最核心的部分, 也是客户最关注的部分。这一部分的实 现,通常需要技术专家和领域专家通力 合作。
业务逻辑层主要承担了以下职责: 1.对不同数据访问层的封装。使得表示层可以不关心具 体的数据访问层。 2.业务逻辑数据的填充与转换。如管理员口令的加密。 3.核心业务的实现。这里很多业务逻辑只有一行代码, 即一个业务逻辑方法恰好对应一个数据访问方法,但是也有 通过多个数据访问方法实现业务的。如AdminBLL中的 ChangePassword方法就调用了AdminDAL的GetByID和Update 两个方法。另外,虽然许多方法只调用一个数据访问方法, 但是从命名看也能看出两者着眼点的不同。如AdminDAL中的 GetByNameAndPassword,这个名字显然是从数据库的角度看 问题——指按照指定的Name和Password两个字段的值取出相 应信息,至于这样做的业务意义它不需要知道。而AdminBLL 中,调用它的方法叫Login,这是从业务角度看问题——即 这个方法是管理员登录
这里设计的分层架构,层与层之间应该 是松散耦合的。因为是单向单一调用, 所以,这里的“松散耦合”实际是指上 层类不能具体依赖于下层类,而应该依 赖于下层提供的一个接口。这样,上层 类不能直接实例化下层中的类,而只持 有接口,至于接口所指变量最终究竟是 哪一个类,则由依赖注入机制决定。
配置 首先,需要在Web工程的Web.config 文件的<appSettings>节点下添加如下两 个项: <add key="DAL" value=""/> <add key="BLL" value=""/> 这两个配置选项分别存储要应用的 数据访问和也业务逻辑层的程序集名称 。value目前是空,是因为目前还没有各 个层次的具体实现。
分层架构概要设计
架构设计基本原则
这里,将描述一些在这个架构设计中的 基本原则,其中很多都是经典的设计原 则
逐层调用原则及单向调用原则
现在约定将N层架构的各层依次编号为1、2、…、K、 …、N-1、N,其中层的编号越大,则越处在上层。那 么,我们设计的架构应该满足以下两个原则:
第K(1<K<=N)层只准依赖第K-1层,而不可依赖其他底层。 如果P层依赖Q层,则P的编号一定大于Q。
第三步,新建一个工程。 我们要新建一个工程AccessDAL,用 来存放Access数据访问层的代码。 准备工作做完了,现在来实现具体 的代码。
1.编写数据访问助手类 因为很多数据访问操作流程很相似,所以,这 里将一些可复用的代码抽取出来,编写成助手类, 以此减少代码量,提高代码复用性。 这个助手类放在AccessDAL下,叫 AccessDALHelper,主要负责Access数据库的访问 。它包括三个方法: GetConnectionString:从配置文件中读取配 置项,组合成连接字符串。 ExecuteSQLNonQuery:执行指定SQL语句,不 返回任何值,一般用于Insert,Delete,Update命 令。 ExecuteSQLDataReader:执行SQL语句返回查 询结果,一般用于Select命令。
依赖倒置原则
从这两个定义可以看到,所谓的依赖倒置原则 ,正是上面提到针对接口编程,而不是针对实 现编程,两者在本质上是统一的。 综上所述,可以看出,本课题设计的分层 架构,应该是这样一种架构: 1.N层架构的各层依次编号为1、2、…、K 、…、N-1、N,其中层的编号越大,则越处在 上层。 2.架构中仅存在一种依赖,即第K层接口 依赖第K-1层,其中1<K<=N。
实现缓存操作辅助类 为实现缓存操作,我们将缓存操作 封装成一个辅助类,放在Utility工程下
封装依赖注入代码 因为很多依赖注入代码非常相似, 为了减少重复性代码,我们将可复用的 代码先封装在一个类中。 (这个类放在 Factory工程下)
实现工厂 下面使用两个辅助类,实现数据访 问层工厂和业务逻辑层工厂。
单一归属原则
在这个架构中,任何一个操作类都应该 有单一的职责,属于单独的一层,而不 能同时担负两种职责或属于多个层次( 实体类及辅助类可以被多个层使用,但 它们不属于任何一个层,而是独立存在 )。
层次划分
目前,典型的分层架构是三层架构,即 自底向上依次是数据访问层、业务逻辑 层和表示层。 这种经典架构经历了时间的考验和 实践的多次检验,被认为是合理、有效 的分层设计,所以,在本文中,将沿袭 这种经典架构,使用数据访问层、业务 逻辑层和表示层的三层架构体系。
接口的设计与实现
源自文库
对于接口的设计。这里包括数据访问层接口和业务逻 辑层接口。在分层架构中,接口扮演着非常重要的角 色,它不但直接决定了各层中的各个操作类需要实现 何种操作,而且它明确了各个层次的职责。接口也是 系统实现依赖注入机制不可缺少的部分。 接口设计将按如下顺序进行: 1.首先由需求分析,列出主要的UI部分。 2.分析各个UI需要什么业务逻辑支持,从而确定 业务逻辑层接口。 3.分析业务逻辑层接口需要何种数据访问操作, 从而确定数据访问层接口。 另外,为保证完全的面向对象特性,接口之间的数据 传递主要靠实体类或实体类集合,禁止使用DataTable 等对象传递数据。
职责划分
数据访问层——负责与数据源的交互,即数据的插入 、删除、修改以及从数据库中读出数据等操作。对数 据的正确性和有效性不负责,对数据的用途不了解, 不负担任何业务逻辑。 业务逻辑层——负责系统领域业务的处理,负责逻辑 性数据的生成、处理及转换。对流入的逻辑性数据的 正确性及有效性负责,对流出的逻辑性数据及用户性 数据不负责,对数据的呈现样式不负责。 表示层——负责接收用户的输入、将输出呈现给用户 以及访问安全性验证。对流入的数据的正确性和有效 性负责,对呈现样式负责,对流出的数据正确性不负 责,但负责在数据不正确时给出相应的异常信息。
封装变化原则
封装变化的原则定义为:找出应用中可 能需要变化之处,把它们独立出来,不 要和那些不需要变化的代码混杂在一起 。
开放-关闭原则
开发-关闭原则定义为:对扩展开放,对 修改关闭。 具体到N层架构中,可以描述为:当 某一层有了一个新的具体实现时,它应 该可以在不修改其他层的情况下,与此 新实现无缝连接,顺利交互。
表示层模块:程序及可视元素的集合,负责完成表示层的具体功能。
IoC容器模块:负责依赖注入的实现。 辅助类模块:完成全局辅助性功能。
模块划分及交互设计
各 模 块 见 交 互 关 系 如 下
实体类的设计与实现
实体类是现实实体在计算机中的表示。它贯穿 于整个架构,负担着在各层次及模块间传递数 据的职责。 一般来说,实体类可以分为“贫血实体类”和 “充血实体类”,前者仅仅保存实体的属性, 而后者还包含一些实体间的关系与逻辑。 大多情况下,实体类和数据库中的表(这里指 实体表,不包括表示多对多对应的关系表)是 一一对应的,但这并不是一个限制,在复杂的 数据库设计中,有可能出现一个实体类对应多 个表,或者交叉对应的情况。
第一步,我们要将Access数据库搭建完成 ,具体做法如下。 在Web工程下新建一个文件夹,命名 为AccessData,并在其中新建一个mdb文 件(即Access数据库文件),按照需求 分析的数据库设计构架,将数据表及表 间关系建好,
第二步,我们要进行一些配置。 打开Web工程下的Web.config文件,在其中的 appSettings节点下,添加如下键值: <add key="AccessConnectionString" value="Provider=Microsoft.Jet.OLEDB.4.0;Data Source={DBPath}"/> <add key="AccessPath" value="~/AccessData/AccessDatabase.mdb"/> 第一条为Access的连接字符串,第二条为 Access数据库文件的路径,其中“~”表示网站根目 录