[Architecture Design] 3-Layer基础架构

[Architecture Design] 3-Layer基础架构

三层式体系结构

只要是软件从业人员,不管是不是本科系出身的,相信对于三层式体系结构一定都不陌生。在三层式体系结构中,将软件开发所产出的程序代码,依照不同用途归类为:系统表示层、领域逻辑层、数据存取层。其中:

  • 系统表示层 (Presentation Layer),用来归类「提供操作接口」的相关程序代码。例如:提供Textbox接受用户输入地址数据、透过MessageBox通知用户处理结果、甚至是提供Web API给远程系统使用,这些程序代码都会被归类在表示层之中。
  • 领域逻辑层 (Domain Layer),用来归类「封装系统逻辑」的相关程序代码。例如:商城系统的商品数据、购物车、对账单,或者是出勤系统的上下班记录、员工数据…等等,这些程序代码都会被归类在领域逻辑层 之中。
  • 资料存取层 (Access Layer),用来归类「实作数据存取」的相关程序代码。例如:将数据存放到SQL Server、或者是从远程WebService取得数据…等等,这些程序代码都会被归赖在存取层之中。

透过三层式体系结构的设计,让开发人员能够粗略的将系统拆解为三个不同面向的分类。透过套用这样的架构设计,在开发过程中,能够减少需要思考的设计内容,让开发人员一次只需要思考某个面向的设计内容。而在后续的维护过程中,也让开发人员能够分门别类的去理解既有的程序内容。

基础架构设计

虽然说,只要是软件从业人员,对于三层式体系结构都不陌生。但是三层式体系结构毕竟是在比较早期的年代所提出,随着面向对象语言的发明、后续DI与IoC概念的加入、以及DDD、TDD等技术的出现。让开发人员在撰写一个套用三层式体系结构的软件系统,需要考虑的方方面面变得越来越多,一层堆一层的知识体系,已经慢慢榨干开发人员的脑细胞活力。不过还好的是,现代的软件业界出现了「软件架构师」这一个职缺。在项目开发的过程中,透过软件架构师的努力,来消化知识体系的堆积,产出为符合项目需求、团队能力的软件架构。后续团队内的开发人员只要照着软件架构去按图施工,就能生产具有一定水平的系统软件。

接下来的内容,介绍一个以三层式体系结构为核心所发展出来的基础软件架构。期望让没有软件架构师加持的开发人员,能有一个基础的软件架构来按图施工,除了增加软件开发的速度之外,也让项目产出的程序代码能够满足:进行单元测试、重用系统逻辑、抽换数据源….等等非功能性需求。

领域逻辑层 (Domain Layer)

接着从三层式体系结构中的领域逻辑层来看看,领域逻辑层所包含的对象该如何设计。领域逻辑层主要用来归类「封装系统逻辑」的相关程序代码,而「系统逻辑」这个概念,可以拆解为几个模式来分门别类的设计:

  • Entity:Entity主要用来将数据单元封装成为对象。在设计系统的时候,一个一个系统要处理的数据单元可以封装成为Entity对象,每个Entity对象的属性则是用来提供数据单元所包含的数据内容,像是上图中的Employee对象、Product对象用来代表系统所要处理的员工数据、商品数据。另外,Entity对象的方法,也用来封装各种运算功能;例如一个判断员工是否成年的功能,就可以选择封装成为Employee对象的方法来提供使用。
  • IRepository:IRepository主要用来定义Entity对象进出领域逻辑层的接口(系统边界)。在设计系统的时候,当有Entity对象需要进出数据库或是远程服务,可以将进出功能封装成为IRepository接口的方法,像是上图中的IEmployeeRepository接口用来提供Employee对象进出系统数据库的方法定义。另外,IEmployeeRepository接口的方法,也用来封装各种查询功能;例如一个查询所有售价少于100元商品的功能,就可以选择封装成为IEmployeeRepository界面的方法来提供使用。
  • Service:Service主要用来封装系统终难以归类的系统功能。在设计系统的时候,当有一个系统功能分派给Entity对象不适合、分派给IRepository接口也不适合的时候,就可以考虑额外将这个系统功能封装为Service对象。例如一个转账功能,可能牵扯好几个帐户、并且需要许多交易纪录,这时分派给Entity对象、IRepository接口会让这两者的耦合度过高,这时就可以选择封装一个独立的转账服务对象来提供使用。
  • Context:Context主要用来提供统一的进入点来使用系统功能。在设计系统的时候,系统功能会被分派到 Entity对象、IRepository接口、Service对象来提供使用,这时加入Context对象将原本四散的职责黏合,能够简化使用时的复杂度。另外一个进阶的议题,是统一由Context对象来提供注入与保存IRepository接口实作,也是一个减少领域逻辑层与DI Framework相依的一种解决方案。

透过上列几个模式来分门别类的设计,基本上就可以将领域逻辑层所要封装的系统逻辑,都建立成为一个个的对象。而套用这样的设计架构,因为透过IRepository接口来建构出系统边界,所以让单元测试得以进行;透过Context对象来简化系统复杂度,让重用系统逻辑、抽换数据源变成可行。

系统表示层 (Presentation Layer)

谈完最核心的领域逻辑层,接着看系统表示层就比较轻松一点了。系统表示层 (Presentation Layer),用来归类「提供操作接口」的相关程序代码,这边所定义的操作接口有一个很重要的概念是,操作接口包含:

  • 给人使用的UI接口:给人使用的UI接口,就是应用程序的用户接口。透过应用程序的所提供的可视化接口,系统就可以提供信息给用户,并且接收用户所输入的数据以及操作。
  • 给系统使用的API接口:给系统使用的API接口,就是服务程序的通讯接口。服务程序提供各种通讯接口来开放功能给外部系统使用,这些接口可能会是WCF、Web Service、甚至是最近很夯的SignalR,都会是系统所提供的API接口的其中一种可选择方案。

回过头综观整个系统表示层的设计,简单说就是对上提供接口给其他人使用,对下依照接口操作去使用领域逻辑层所提供的功能。例如说:领域逻辑层提供了一个「查询所有售价少于100元商品的功能」,当系统提供UI接口给人使用时,可能就会提供一个显示页面来条列所有从资料存取层查询出来的商品;当系统提供API接口给系统使用时,可能就会建立一个Web API的方法来提供查询,并且使用JSON格式来回传所有从数据存取层查询出来的商品。

当然,没有好处的事,我们不要去做。系统中切割出系统表示层,在项目开发的过程中会得到一个很大的好处就是:系统表示层是用户最会修改的设计。做项目时,使用者最会有意见的就是系统表示层,当开发人员将系统表示层独立切割开来,就算画面怎么变化背后的逻辑还是不会变。这样开发人员心理上,就能比较轻松去面对客户的挑战(反正也只是画面调调而已),而实质上因为不会动到核心的领域逻辑层,也避免了改这边坏那边的窘境。

资料存取层 (Access Layer)

最后看看在三层式体系结构中最单纯的数据存取层。数据存取层 (Access Layer),用来归类「实作数据存取」的相关程序代码,这边所定义的实作数据存取,就是很简单的实作领域逻辑层中所定义的IRepository接口。但是虽然说是很简单的实作IRepository接口,却也是包含了许多的变化:

  • 数据存放到数据库(远程):一般的Web网站、应用程序,会选择将数据存放到远程的Sql Server。
  • 数据存放到数据库(近端):在一些APP的开发项目中,会选择将数据存放在本地端的SQLite。
  • 数据存放到系统(远程):在一些APP的开发项目中,会选择将数据透过Web Service存放在远程的服务器上。
  • 数据存放到系统(近端):在一些复杂的开发项目中,会选择数据源是另外一个领域逻辑层。例如:一个购物商城的客户数据源,有可能是由另外一个客户管理系统来提供。
  • 依照运行状态决定:在一些APP的开发项目中,会依照网络联机状态来决定数据存放位置。例如:网络断线时存取本地端的SQLite、网络联机时存取远嘟的WebService。
  • ......

在上列这些可以选择的解决方案中,比较有趣的是数据存放到系统、依照运行状态决定这两个变化样式。其中数据存放到系统这个变化样式,为系统加入了串接各种系统的可能性,让系统能够像堆积木一样,一个串一个的互相结合,大幅增加系统的重用性。而依照运行状态决定,则是一个重用程序代码的设计,只要额外加入一个IRepository实作来判断运行状态,并且分配该去呼叫哪个现有的Sql实作、Web实作,就可以重复使用既有程序。

同样的,没有好处的事,我们不要去做。系统中切割出数据存取层,在项目开发的过程中会得到一个很大的好处就是:数据存取层是开发过程中最会修改的设计。做项目的时候,系统开发的过程中很多数据字段都要到项目中后期客户才会发现(很神奇,但真实)。当开发人员将资料存取层独立切割开来,并且在数据字段定案之前,都先透过对象操作的方式来提供数据,并在最后的最后才去建立SQL数据表。这样在开发的过程中,就不需要反复的调整数据表字段、检查对应的SQL指令,大量减少开发人员花在这些琐碎工作上的时间成本。

下载

范例程序代码:点此下载

时间: 2024-10-06 16:17:47

[Architecture Design] 3-Layer基础架构的相关文章

[Architecture Design] 跨平台架构设计

[Architecture Design] 跨平台架构设计 跨越平台 Productivity Future Vision 2011 在开始谈跨平台架构设计之前,请大家先看看上面这段影片,影片内容是微软在2011年所描绘的未来生活蓝图.在观看的过程中,请大家以「软件开发人员」的角度来思考,想想软件开发人员在其中扮演甚么样的角色. 「Productivity Future Vision 2011」 这段影片里面所描绘未来产品,把时间轴拉到现在来看,其实有许多概念已经悄悄融入我们的生活之中.像是影片

ITIL《信息技术基础架构库》

1. ITIL 自上世纪70年代开始,个人计算机以及计算机网络开始在欧美发达国家普及.随着时间的推移,信息系统的规模越来越大,人们对信息系统的依赖也越来越强.特别是到了80年代,互联网开始普及,信息系统的复杂度增加,IT部门所提供的IT服务,其质量并不令人满意,有时甚至严重影响业务部门的工作.越来越多的人意识到,需要一套方法对IT服务进行管理,英国政府首先采取了行动. 英国计算机和电信局(CCTA),组织一批专家开始研究与开发一套有效的.可量化的IT资源使用和管理方法.这个项目的最终成果是198

【Windows】Windows Server 2008 R2:核心基础架构

核心基础架构 Windows Server提供了核心基础架构服务以支持网络的运行.Windows Server技术已经成熟了,其中的角色和功能也同样成熟了.Windows Server 2008 R2继续改进了核心基础架构服务,这些服务一直都是Windows Server的一部分,它们为我们的业务提供了一个稳固的基础.点击以下核心基础架构角色以了解更多: Active Directory(AD) 应用程序和Web服务 可用性和可量测性 备份和恢复-Windows Server Backup Br

在C7000+VMware vSphere5.5环境中的基础架构服务器部署实例

主题:使用HP C7000设备在VMware vSphere环境中部署企业高可用性基础架构服务器 目标:在C7000中使用BL460G8部署VMware vSphere服务器虚拟化方案,完成企业级高可用性基础架构服务. 硬件 1:1台HP C7000刀框 2:3台HP BL460G8服务器 3:2个HP Virtual Connect FlexFabric 10Gb/24-port Module 4:1台HP P4500存储 需要的图表 设计整体逻辑拓扑图 配置信息参数图表 IP地址规划图表 E

Web基础架构:负载均衡和LVS

在大规模互联网应用中,负载均衡设备是必不可少的一个节点,源于互联网应用的高并发和大流量的冲击压力,我们通常会在服务端部署多个无状态的应用服务器和若干有状态的存储服务器(数据库.缓存等等). 一.负载均衡的作用 负载均衡设备的任务就是作为应用服务器流量的入口,首先挑选最合适的一台服务器,然后将客户端的请求转发给这台服务器处理,实现客户端到真实服务端 的透明转发.最近几年很火的「云计算」以及分布式架构,本质上也是将后端服务器作为计算资源.存储资源,由某台管理服务器封装成一个服务对外提供,客户端 不需

linux通用邻居基础架构

1.为每一个协议提供一个缓存来存放L3到L2的转换结果. 2.提供在缓存中添加.删除.改变和查找一个特定映射项的函数.查找函数必须要快,因为它会影响整个系统的性能. 3.为每一个协议缓存的数据项提供一种老化机制. 4.当缓存已满时并且正好要创建新的映射项时,提供选择替换策略. 5.为每一个邻居提供一个请求队列.当准备要发送一个封包并且其L2地址还不在地址缓存中是,就必须把这个封包放到缓冲区中,直到发出solicitation请求,并且收到应答.参见27章排队一节. 为了让每一种协议都适应邻居自系

微软云基础架构Hyper-scale Datacenter

每天醒来,可能很多人的习惯都是打开手机,看看微信,刷刷朋友圈,或者看看新闻,去咖啡店,打开电脑搜索一些关键字,观看视频,电视剧--可是你有没有想过你每一次键盘的敲击,每一次微信的语音的发送,数据会流向哪里,会怎么传播,我们怎么会快速的得到离我最近的餐厅信息?事实上,你所使用的所有这些服务,都运行在一个个的数据中心中,而数据中心正是信息世界中数据交换,流动,计算的心脏. 越来越多的大型IT公司将自己的数据中心和云端基础设施作为其重要的战略资产和核心竞争力的一部分,也有人可能看到过网上流出的goog

代码抄袭检测系统的设计和实现(1)--需求分析和基础架构

前言: 其实挺意外的, 最近和大学的老师联系, 得知4年前写的代码抄袭检测系统还在运行, 又惊又喜, 还以为早就替换升级了.  千百次回眸, 可惜界面依旧不给面子的简陋, 不过"金窝, 银窝, 不如自家的草窝", 脑补之后, 越看越帅气, ^_^!!. 让我们暂时抛开"娇俏动人"的web界面, 来谈谈背后"核心"的相似检测算法. 算法未必华丽, 效果未必惊艳, 但愿与大家一起分享, 与君共勉. 场景: 让我们来玩个游戏, 假设我们是懒得"

nodejs学习笔记_nodejs和PHP在基础架构上的差别--共享状态的并发

绝大多数对于Node.js的讨论都把关注点放在了处理高并发能力上,做开发的时候一定要明确node内部做出的权衡,以及node应用性能好的原因. node 为javascript引入了一个复杂的概念,:共享状态的并发. node採用一个长期执行的进程 而php在apache中会产生多个进程 例如以下图所看到的: 代码验证: PHP: <?php $i = 0; $i++; echo $i nodejs: var http = require('http'); var i=0; http.creat