[Architecture Design] 3-Layer基础架构

似乎 Snapchat 要做的不是花钱聘请著名说客,去为他们向国会解释软件是怎样运作,而是花更多钱去聘请保安专家。话说 Snapchat 在昨天公布了一个新的身份验证系统,用户需要选中吉祥物来证明自己不是恶意的机械人账户,可是一位聪明的黑客 Steven Hickson 声称他只花了 30 分钟左右就写出能够破解系统的程序。简单来说,这只是一个能够以参考图片,基于图中特征来找出「最佳」配对图的程序,他在一些测试中得到 100% 的准确度;要记着,他只花了不足一小时,而有关程序代码亦不足 100 行,能够得到这样的成绩可说是了不起。最后,Hickson 更在 Github 一提供了有关的程序代码,不知道 Snapchat 会如何应对呢?干脆聘请他?经由:Engadget引用来源:Steve's Computer Vision Blog

如果你家里有一台24小时在线的计算机,比如一台家用服务器,那么你很可能需要通过终端运行一些命令来控制它,比如启动进程、定位问题等等。DIY极客Steve想出了一种方法,可以通过发送手机短信来在树莓派上运行终端命令。

[Architecture Design] 3-Layer基础架构

图片 1

三层式体系结构

图片 2

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

  • 系统表示层 (Presentation Layer),用来归类「提供操作接口」的相关程序代码。例如:提供Textbox接受用户输入地址数据、透过MessageBox通知用户处理结果、甚至是提供Web API给远程系统使用,这些程序代码都会被归类在表示层之中。

  • 领域逻辑层 (Domain Layer),用来归类「封装系统逻辑」的相关程序代码。例如:商城系统的商品数据、购物车、对账单,或者是出勤系统的上下班记录、员工数据…等等,这些程序代码都会被归类在领域逻辑层 之中。

  • 资料存取层 (Access Layer),用来归类「实作数据存取」的相关程序代码。例如:将数据存放到SQL Server、或者是从远程WebService取得数据…等等,这些程序代码都会被归赖在存取层之中。

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

 

基础架构设计

图片 3

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

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

Steve使用了Google Voice服务,通过一个简单的程序每分钟检查一次发送的信息。如果他通过手机发送的短信以“cmd”开头,他的目标计算机就会运行之后的命令。简单的说,这套机制允许Steve通过SMS来SSH到他的电脑上。你可能不会用这种方式来完成一些复杂的任务,但是当你不在家又希望能控制电脑时,这种方法就非常实用。

领域逻辑层 (Domain Layer)

图片 4

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

  • 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)

图片 5

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

  • 给人使用的UI接口:给人使用的UI接口,就是应用程序的用户接口。透过应用程序的所提供的可视化接口,系统就可以提供信息给用户,并且接收用户所输入的数据以及操作。

  • 给系统使用的API接口:给系统使用的API接口,就是服务程序的通讯接口。服务程序提供各种通讯接口来开放功能给外部系统使用,这些接口可能会是WCF、Web Service、甚至是最近很夯的SignalR,都会是系统所提供的API接口的其中一种可选择方案。

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

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

Raspberry Pi 树莓派搭LAMP服务器

资料存取层 (Access Layer)

图片 6

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

  • 数据存放到数据库(远程):一般的Web网站、应用程序,会选择将数据存放到远程的Sql Server。

  • 数据存放到数据库(近端):在一些APP的开发项目中,会选择将数据存放在本地端的SQLite。

  • 数据存放到系统(远程):在一些APP的开发项目中,会选择将数据透过Web Service存放在远程的服务器上。

  • 数据存放到系统(近端):在一些复杂的开发项目中,会选择数据源是另外一个领域逻辑层。例如:一个购物商城的客户数据源,有可能是由另外一个客户管理系统来提供。

  • 依照运行状态决定:在一些APP的开发项目中,会依照网络联机状态来决定数据存放位置。例如:网络断线时存取本地端的SQLite、网络联机时存取远嘟的WebService。

  • ......

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

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

Raspberry Pi 树莓派上安装Weston 

下载

范例程序代码:点此下载

在树莓派Raspberry Pi上安装游戏模拟器

附上Steve的博文:

下面这个程序能让你通过短信息来控制计算机,把它当成SSH over短信就好了。设计这个是为了能快速智能化地查看未读的Google Voice信息。如果传送了特定的参数,树莓派就会运行你发送的命令并返回结果。这个程序需要用到curl和libboost1.50-regex。安装脚本会自动安装curl和boost-regex。

注意:该程序能工作在任何Linux系统上,但我是在树莓派上使用它的,因此如果你使用的是别的平台,那么你就要自行编译了(记得要修改Makefile中的flags)。

本文由金沙官方网站发布于科学技术,转载请注明出处:[Architecture Design] 3-Layer基础架构

您可能还会对下面的文章感兴趣: