**《微软应用架构指南 (第2版)》
========== ========== ==========
[作者] (美) Patterns & Practices
[译者] (中) 朱晔 高翔 王敏
[出版] 电子工业出版社
[版次] 2010年11月 第1版
[印次] 2010年11月 第1次 印刷
[定价] 69.00元
========== ========== ==========
【前言】
(P001)
开发人员和方案解决架构师通常是游走在“黄金方案”和“即时方案”之间。
架构就是利用现有的技术和工具来创造尽可能多的商业价值,一方面关注现有业务所提出的需求和限制,另一方面着眼于未来通过可伸缩性、灵活性以及可维护性等方面最大化价值。
【第01章】 【什么是软件架构】
(P003)
软件应用架构是一个结构化解决方案,这种结构化解决方案一方面可以满足所有技术和运营需求,另一方面可以满足常见的质量特性 (quality attribute) 要求,例如性能、安全以及可管理性等。它涵盖了受多重因素影响的一系列决策,每种决策对质量、性能、可维护性及应用程序总体的成功都有相当大的影响。
(P004)
一个失败的架构带来的风险包括软件不稳定、不能支持既有或将来的业务需求、或难以在生产环境中部署和管理。
系统在设计的时候需要考虑用户、系统 (IT基础结构) 和业务。对于每一个方面,您都应该列出关键应用场景,并找出重要质量特性 (例如可靠性或可伸缩性) 和令人满意或不满意的关键点。如果可能的话,在每一个需要考虑的方面,都建立衡量得失的标准。
架构关注构成应用程序的主要元素和组件的使用和它们之间的交互。而设计则主要关注与数据结构和算法的选择,以及组件细节的实现。
架构师必须考虑设计决策导致的总体效果,以及与生俱来的权衡,包括众多质量属性之间的权衡和用户、系统和业务需求之间的权衡。
要记住,架构应该 :
- 展示系统的结构但是隐藏实现细节;
- 意识到所有用例和应用场景;
- 力求顾及各参与者的需求;
- 处理功能和质量需求;
(P005)
使用那些在大量解决方案中经过验证的,可以解决常见问题的模式。
不要对架构进行过度设计,尤其是不要针对那些无法验证的事情做出任何假设,我们只需要在设计的过程中为将来可能的变化留出余地即可。
【第02章】 【软件架构的关键原则】
(P007)
架构注重把组件进行组织以支持特定功能。
(P008)
在设计应用程序或系统的时候,软件架构师的目标是通过把设计分割为不同的关注点来尽量减少复杂度。
对于每一个点,我们设计的组件就关注此特定点,不应混合其他关注点的代码。
(P009)
关注点分离 —— 把您的应用程序分解为尽可能不发生功能重叠的不同特性。这样做最大的好处是某个特性或功能可以独立于其他特性或功能进行优化。
明确层之间如何通信 —— 如果允许应用程序中的层和其他所有层进行通信或依赖,可能会导致解决方案更难理解和管理,需要考虑清楚层间的依赖和层与层间数据的流动。
组件或对象不应该依赖其他组件或对象的内部细节 —— 每一个组件或对象应该只调用另一个组件或对象的一个方法,并且这个方法知道如何处理请求,如何把它转发到合适的子组件或其他组件,这有助于创建可维护性和可适应性更高的应用程序。
(P010)
确保横切代码尽可能从应用程序业务逻辑中抽象出来 —— 横切代码指的是有关于安全、通信或诸如日志和指示器等运营管理的代码。
(P011)
每一个应用程序设计都必须考虑安全性和性能,但不是每一个设计都需要考虑互操作性和可伸缩性。
【第03章】 【架构模式和风格】
(P013)
架构风格 (architectural style) 有时候又被称作架构模式,它是一组原则 —— 为一族 (a family of) 系统提供抽象框架的粗粒度的模式。
理解架构风格有很多好处,最大的好处在于它提供了通用表达方式,还为技术无关的讨论提供了机会,能让我们在不涉及具体细节的情况下针对模式和原则进行高层的讨论。
(P014)
软件系统的架构几乎都不会局限于单个架构风格,而通常是使用架构风格的组合来构成完整的系统。
(P016)
最简单的 客户端 / 服务端 系统包含了可以由多个客户端直接访问的服务端应用程序,也称作两层架构风格。
(P017)
可以使用诸如依赖注入 (Dependency Injection) 模式或者是服务定位器 (Service Locator) 之类的设计模式来管理组件之间的依赖关系,并且提供松散的耦合和重用。
(P018)
为应用程序进行正确的分层可以帮助您有效地分离关注点,从而增进灵活性和可维护性。
分层架构风格通常称为重用的倒金字塔 (inverted pyramid of reuse) ,每一层对直接下层的职责和抽象进行聚合。对于严格的分层结构来说,层中的组件只能和相同层或直接下层中的组件进行交互,而较松散的分层结构则允许层中的组件和相同层以及任何下属层中的组件进行交互。
应用程序的层可能放在相同的物理机器上 (相同物理层) 或是分布在独立的机器上 (N 物理层),并且每一层中的组件通过明确定义的接口来和其他层中的组件进行通信。
可重用 —— 下层对上层没有依赖,这也就使得下层可以在其他应用场景中被重用。
松耦合 —— 层之间的通信基于抽象和事件,这也就提供了层和层之间的松耦合。
(P019)
性能 —— 通过把逻辑层分布到多个物理层中可以提高扩展性、容错性 (fault tolerance) 和性能。
(P020)
消息总线架构通常使用消息路由或 发布 / 订阅 模式,并且通常使用诸如消息队列的消息系统来实现。
复杂的处理逻辑 —— 可以通过整合一组小的操作来构成复杂操作,每一个小操作都完成特定任务,多个小操作组合成一个多步操作。
(P021)
N 层或三层是一种架构部署风格,它以一种和分层风格很相似的方式把功能分割为不同的片段,只不过每个片段作为一个物理层,将会分布在物理上分离的计算机上。它从面向组件的方式发展而来,通常使用特定于某个平台的方式而不是基于消息的方式来通信。
N 层应用架构的主要特征是 : 应用程序功能分离,服务组件、组件的分布式部署,提供增强的可伸缩性、可用性、可管理性及充分利用资源。除了直属上层和下层之外,每一个物理层完全独立于其他的层。n 层只知道如何处理 n+1 层的请求,如何把请求返回给 n-1 层 (如果有的话) ,以及如何处理请求的结果。一般层之间的通信是异步的,以便更好地支持可伸缩性。
N 层架构通常至少有三个分离的逻辑部分,每一部分都部署于独立的物理服务器上,每一部分负责特定的功能。在使用分层设计方式的时候,如果有超过一个服务或应用程序使用逻辑层的功能就把它部署为物理层。
N 层 / 三层 架构风格的主要优势在于 :
-
可维护性 —— 由于每一层相对于其他层来说是独立的,更新或修改部分都不会对整个应用程序发生影响;
-
可伸缩性 —— 由于物理层基于逻辑层来部署,横向扩展应用程序就变得相当简单;
-
灵活性 —— 由于每一层都独立管理和扩展,也就增加了灵活性;
- 可用性 —— 应用程序可以使用易于扩展的组件来形成模块化的系统,增加了可用性;
(P022)
通过使用一系列的协议和数据格式来交流信息, SOA 架构风格可以把业务处理包装成可互操作的服务,客户端和其他服务可以访问运行于相同物理层的本地服务,也可以通过连接的网络访问远程服务。
【第04章】 【架构和设计的方法】
(P026)
架构过程应该是迭代和增量的方式。
(P027)
在架构和设计的过程中,用例 (use case) 描述的是一组交互行为,它可以是系统和一个或多个因素 (用户或另外一个系统) 之间的交互。而应用场景 (scenario) 描述的是广义上用户和系统的交互,这种交互并不通过用例的路径。
(P028)
架构风格是一组原则。您可以把它认为是一个粗粒度的模式,它可以为一族系统提供抽象框架。每一个风格定义了一组规则,它指定构成系统的组件类型、组件之间的关系、组装方式的约束以及组装时使用的一些假想。
架构风格可以提高系统的分层程度,并且通过为经常发生的问题提供解决方案来提升设计的重用性。
应用程序往往使用多个风格的组合。
(P029)
在选择您设计中会使用的技术的时候,您需要考虑哪些技术可以支持所选的架构风格、应用程序类型及应用程序的关键质量特性。
是否可以画出架构很重要。
【第05章】 【分层应用程序指导原则】
(P039)
层关注的是组件和功能的逻辑划分 (logical division) ,不考虑组件的物理位置。层可以位于不同的物理层也可以属于相同的物理层。
我们需要理解逻辑层 (layer) 和物理层 (tier) 的区别。逻辑层描述的是应用程序中功能和组件的逻辑分组;而物理层 (Tier) 描述的是把功能和组件从物理上分布到独立服务器、计算机、网络或远程位置。
把超过一个逻辑层放在同一个物理机器上 (一个物理层) 很常见。
层有助于区分组件进行的不同类型的任务,这样使得我们的设计可以很容易支持组件重用。
每一个逻辑层包含许多独立的组件类型并分组成子层,每一个子层执行特定类型的任务。
把应用程序分割为具有不同角色和不同功能的层不仅有助于最大化代码的可维护性,而且能通过改变部署方式最优化应用程序的工作方式,以及提供一个清晰的描述展示各个位置上必须实现的技术或设计决策。
从最高级的和最抽象的角度来说,任何系统在逻辑架构层面都可以看作是把一组相互协作的组件分组成逻辑层。
(P040)
表现层 —— 这个层包含面向用户的功能,负责管理用户和系统之间的交互,通常还包含一些组件,我们可以利用这些组件来访问封装在业务层的核心业务逻辑。
业务层 —— 这个层实现了系统的核心功能并且封装了相关业务逻辑。它通常由一些组件构成,一些组件可能会暴露服务接口供其他调用者使用。
数据层 —— 这一层提供针对寄存在系统边界内的或者由其他联网系统暴露的数据的访问,这种访问可能是通过服务的方式进行的。
从较高的层面来看,基于服务的解决方案可以看作是由多个服务构成,每一个服务通过传递消息和其他服务进行通信。从概念上来说,服务可以看作是整个解决方案的一些组件。然而,在内部每一个服务和其他任何应用程序一样都由软件组件构成,并且这些组件可以在逻辑上分组为表现层、业务层和数据层。
(P041)
如果应用程序必须为其他应用程序提供服务,或者要实现一些直接提供给客户端的特性,通常的方式就是使用服务层来暴露应用程序的业务功能。
(P042)
在设计应用程序的时候,第一件事情就是关注最高层次的抽象,也就是功能的分层,然后必须为每一层 (取决于设计的应用程序的类型) 定义公共接口。定义了层和接口之后,还必须决定应用程序的部署方式,最后选择要使用的通信协议,用于逻辑层和物理层之间的交互。
使用分层的方式可以改善应用程序的可维护性,并且在需要改善性能的时候可以更方便地进行横向扩展 (scale out) 。
确定分层策略中至关重要的第一步就是为应用程序确定合适的分层粒度。
(P043)
为了保持灵活性,总是需要确保层之间的交互是松耦合的。
采用分层方式会增加一些复杂度,并且可能会增加初始的开发时间,但是如果正确实施的话,会极大提高应用程序的可维护性、可扩展性和灵活性。必须在重用性、松耦合和影响性能、增加复杂度之间进行权衡选择。总体上来说,分层设计提供的灵活性和可维护性的优势远远超过了使用不分层的紧密耦合设计带来微弱的性能上的提升。
业务应用程序中最常见的作法是把表现、服务、业务和数据访问功能分成独立的层。一些应用程序还引入报表、管理或基础结构层。
如果需要增加层的话请慎重考虑,如果对相关联的组件进行逻辑分组不能明确增加应用程序可维护性、可伸缩性或灵活性的话,就不应该增加层。
只有在必要的时候才应该跨越独立的物理层来分布逻辑层和组件。
(P044)
找出应用程序中所有横切关注点很重要,尽可能为每一个关注点设计独立的组件。这种方式可以帮助您获得更好的重用性和维护性。
在为层定义接口的时候,首要的目标是实现层之间的松耦合。也就是说层不应该暴露内部细节让其他层进行依赖。而是应该设计层的接口,通过提供能够隐藏层中组件细节的公共接口来最小化依赖。这种隐藏称作抽象 (abstraction) ,并且有很多不同的方式来实现。
(P045)
一个层不会依赖于另外一个层,层都依赖于公共接口。
【第06章】 【表现层指导原则】
(P047)
表现层包含的组件可以实现和显示用户界面并且管理用户交互。它包含一些用于用户输入和显示的控件及一些组织用户交互的组件。
(P049)
缓存是用来提高应用程序性能和 UI 响应速度最好的方法之一。
(P050)
对长时间运行的行为,要为用户提供进度反馈。考虑允许用户取消长时间运行的操作。
(P051)
除非捕获的异常能处理,否则别随便使用自定义的异常,并且不要使用异常来控制应用程序的逻辑流程。
(P052)
输入验证应该由表现层来处理,而业务规则验证应该由业务层来处理。
如果您的业务层和表现层在物理上是分离的,业务规则的验证逻辑还应该在表现层也实现一份,以提高可用性和响应速度。
(P055)
对于 ASP.NET ,要小心地使用 ViewState ,因为它可能会在每一次往返中增加数据量,降低应用程序的性能。应考虑配置页面使用只读会话,甚至可以的话,考虑不使用会话。
【第07章】 【业务层指导原则】
(P060)
要最大化重用,业务逻辑组件不应该包含任何只能用于特定用例或应用场景的行为或应用程序逻辑。
在设计业务层的时候,软件架构师的目标是通过把任务分成不同的关注点来最小化复杂度。
对于每一个点,您设计的组件都应该关注在特定点上,并且不应该包含和其他关注点相关的代码。
应该尽可能使用独立的业务层来提高应用程序的可维护性。
如果业务层会同时被表现层和外部应用程序使用,就可以选择通过服务来展示业务层。
(P061)
为业务层创建接口的时候使用抽象原则最小化耦合。抽象的技术包括使用公共对象接口,通用接口定义,抽象基类或消息。
为业务层设计有效的身份验证策略对应用程序的安全性和可靠性很重要。
为业务层设计有效的授权策略对应用程序的安全和可靠性很重要。
(P062)
对于角色,应考虑尽可能让粒度变小以减少需要的权限组合数量。
为业务层设计合适的缓存策略对于应用程序的性能和响应速度很重要。
只缓存非常必要的数据。
在为业务层设计组件的时候,应确保它们是高内聚的,并且层间是低耦合的。这样就可以提高应用程序的可扩展性。
(P063)
为业务层设计有效的异常管理解决方案对应用程序的安全性和可靠性很重要。
为业务层设计有效的日志、审计和度量解决方案对应用程序的安全性和可靠性很重要。
为业务层设计有效的验证解决方案对应用程序的可用性和可靠性很重要。
【第08章】 【数据层指导原则】
(P068)
必须确定一个策略来从数据源填充业务实体或数据结构,并且让应用程序的业务层或表现层来使用。
(P069)
批量处理数据库命令可以提升数据层的性能。每一次对数据库执行环境的请求都产生一次开销。通过批量化可以提高吞吐量、减少延迟以降低总开销。因为数据库可以为相近的查询缓存并且重用执行计划,所以批量处理相似查询可以提升性能。
(P070)
如果数据以数据流形式来存储和获取,可以认为这是二进制大对象或 BLOB 。
BLOB 一般用来存储图片数据,但是还可以用来保存对象的二进制表示。
选择合适的数据格式来提供和其他应用程序进行互操作的机制,以及利用序列化来跨进程和跨物理机器进行通信。数据格式和序列化特别重要的另外一个原因是能让业务层存储和获取应用程序状态。
(P071)
尽可能在贯穿应用程序的横切组件中集中进行异常处理逻辑。
(P072)
从存储过程的安全和性能来说,原则上应该使用参数化查询和避免存储过程中构建动态 SQL 。
要记住在存储过程中使用动态 SQL 可能会影响性能、安全性和可维护性。
(P073)
事务是把一组有序信息的交换和相互关联的行为当作原子单元,以满足请求和确保数据库完整性。只有当所有的信息和行为都完成,并且相关数据库改变永久生效的时候,才认为事务完成了。在遇到错误时,事务支持撤销 (回滚) 数据库行为,这有助于保持数据库中数据的完整性。
(P074)
默认情况下微软 SQL Server 数据库为每一个单独的 SQL 语句作为一个单独的事务来执行 (自动提交事务的模式) 。
设计有效的输入和数据验证策略对于应用程序的安全至关重要。
(P075)
DataReader 非常适合只读向前的、每一行都能快速处理的操作。
如果您访问的是 SQL Server 2008 ,可用 FILESTREAM 来得到访问 BLOB 数据的可能和更大的存储灵活性。
(P076)
除非要考虑可扩展性和安全性,否则可把数据访问层和业务逻辑层放在相同的物理层中来以提高应用程序的性能。
【第09章】 【服务层指导原则】
(P081)
如果要通过服务提供应用程序功能的话,把服务功能分割为独立的服务层很重要。
在服务层中需要定义和实现服务接口和数据契约 (或消息类型) 。更重要的是要记住服务永远不应该暴露应用程序中内部的处理细节或使用的业务实体。
服务层应该提供翻译组件翻译业务层实体和数据契约之间的数据格式。
(P082)
服务把服务接口暴露给消息接收方。您可以把服务接口看作一个外观,它把应用程序内实现的业务逻辑 (一般是业务层中的逻辑) 暴露给潜在的消费者。
(P085)
幂等的端点确保了只会处理一个消息,重复的消息会被忽略。
(P086)
服务接口表示的是服务暴露的契约。契约定义了您的服务支持的操作以及这些操作相关的参数和数据传输对象。
对于服务接口的设计最大的错误就是把服务当作细粒度操作的组件。
(P087)
具象状态传输 (REST) 和 SOAP 代表了两种不同的实现服务的风格。从技术角度来说, REST 是一种架构模式,它使用简单的动词来构建,并且很适合 HTTP 。虽然 REST 架构原则可以应用到非 HTTP 的协议上,但是实践中 REST 实现通常和 HTTP 联合使用。 SOAP 是基于 XML 的消息协议,可以和任何通信协议一起使用,包括 HTTP 。
(P089)
为了简单,可使用 ASP.NET WEB 服务 (ASMX) ,但是必须有运行微软 Internet 信息服务 (IIS) 的服务器。
如果您需要诸如可靠会话、事务、活动跟踪、消息日志、性能计数器以及支持多种传输协议等高级特性的话,可考虑使用 WCF 服务。
如果您确定为服务使用 WCF :
-
如果您希望和非 WCF 或非 Windows 客户端进行互操作,可考虑使用基于 SOAP 规范的 HTTP 传输;
-
如果您希望支持局域网内客户端,可考虑使用 TCP 协议和二进制消息编码以及传输安全和 Windows 验证;
- 如果 WCF 客户端位于相同机器,可考虑使用命名管道协议和二进制消息编码;
【第10章】 【组件指导原则】
(P096)
应用程序的每一层都会包含一系列用于实现该层功能的组件。这些组件应该是高内聚松耦合的,以简化重用和维护。
【第11章】 【设计表现组件】
(P103)
UI 的需求取决于应用程序需要支持的功能及用户期望。
对于技术的选择有一个很重要的因素,那就是 UI 需要的功能。
(P104)
根据 UI 的需求,可以确定应用程序的 UI 类型。有许多不同的 UI 类型,每一种都有其优缺点。
富客户端移动应用程序可以支持离线的或间歇性的在线应用场景。而 Web 或瘦客户端移动应用程序只支持持续连续的应用场景。
富互联网应用程序 (RIA) 通常是具有丰富图形用户界面并且运行于浏览器中的 Web 应用程序。
如果应用程序的内容需要被 Web 搜索引擎搜索, Web 应用程序就很适合了。
基于控制台的应用程序提供了纯文字的用户体验,一般运行在诸如命令和窗口或 PowerShell 的命令行外壳中。它们最适合于管理或开发任务,不太可能作为分层应用程序设计的一部分。
在为 UI 组件确定了 UI 类型之后,还必须选择合适的技术。
(P105)
WPF 应用程序通过分离 UI 和底层控制逻辑为 开发人员 / 设计人员 提供交互 —— 允许开发人员关注业务逻辑,而设计人员关注观感。
Silverlight 天生就支持异步 JavaScript 和 XML (AJAX) ,它在 Web 页面中通过 JavaScript 暴露其对象模型,可以使用这项技术让 Web 页面组件和 Silverlight 应用程序进行交互。
(P106)
AJAX 是 .NET 框架 3.5 以及之后版本中 ASP.NET 的重头戏。
Silverlight 控件和包含控件的 Web 页面可以通过使用 JavaScript 来进行交互。
在为 UI 选择实现技术之后,下一步就是设计 UI 组件和表现逻辑组件。
UI 组件是一些给用户显示信息以及接受用户输入的视觉元素。在表现分离模式中,它们一般指视图。
(P107)
除非需要特殊的显示或特殊的数据集合,否则尽量避免创建自定义控件。如果发现 UI 需求不能使用标准控件来实现,可考虑购买控件开发包而不是去自己写自定义控件。如果您必须创建自定义控件,尽可能扩展既有控件而不是去创建新的控件。考虑通过附加控件的行为对控件进行扩展,而不是从控件继承,并且考虑为自定义控件实现设计器支持,让开发人员更容易使用。
表现逻辑组件处理用户界面的非可视化方面的问题。包括验证、响应用户行为、 UI 组件之间的通信以及组织用户交互。
如果 UI 需要复杂的处理或必须和其他层进行通信,可使用表现逻辑组件来和 UI 组件的处理进行解耦。
表现模型组件以一种表现层中 UI 和表现逻辑组件可使用的方式来表示业务层中的数据。
(P108)
表现模型组件应该尽可能同时封装业务层中的数据以及业务逻辑和行为。
特定数据绑定技术可能需要数据源实现特定接口或事件来完全支持数据绑定,比如 WPF 中的 INotifyPropertyChanged 或 Windows Forms 中的 IBindingList 。
【第12章】 【设计业务组件】
(P113)
设计业务组件是一项很重要的任务,如果没有能正确地设计您的业务组件,那么代码将变得难以维护和扩展。
(P114)
应用程序的整体设计和应用程序的类型决定了使用哪些业务组件来处理请求。
【第13章】 【设计业务实体】
(P119)
一般只在表现层需要或逻辑必须和基于 XML 的数据合作的时候才用 XML 。
要注意使用和操作 XML 会消耗大量的内存。
(P120)
微软 .NET 框架提供了可以把 XML 数据反序列化成对象及把对象序列化成 XML 的组件。
必须确定如何跨边界传输业务实体。在大多数情况下,当跨诸如 AppDomain 、进程以及服务接口边界等物理边界传输数据时,您都必须进行数据序列化。甚至在跨逻辑边界传输数据时都要考虑进行序列化。
数据传输对象 (DTO) 是一种设计模式,它可以把多个数据结构打包成单个结构以进行跨边界传输。
(P121)
领域模型使用实体、值对象、聚合根、资源库以及领域服务进行表达,并将其组织成被称作界定的上下文 (bounded context) 的职责分块。
实体 —— 是领域模型中的对象,它们有唯一的标识并且在软件状态发生改变时不会改变。实体封装了状态和行为。
值对象 —— 是领域模型中的对象,用于描述领域驱动的某个方面。它没有唯一标识而且是不可变的。
聚合根 —— 是一种类型的实体,它把逻辑上相关的子实体或值对象分组在一起,并对它们进行访问控制以及协调它们之间交互关系。
资源库 —— 负责接收和保存聚合根,一般使用 对象 / 关系 (ORM) 映射框架。
领域服务 —— 表示操作、行为或业务过程,并且提供引用领域模型中其他对象的功能。有的时候,某个功能或领域的某个方面不能映射到任何具有特定生命周期或实体的对象中,这种类型的功能可以声明为领域服务。
【第14章】 【设计业务工作流】
(P123)
有三种基本的工作流风格 : 顺序、状态机以及数据驱动。对于顺序工作流,任务在指定的一组步骤内迁移,直到其完成。对于状态机工作流,活动被定义成一组状态和事件,事件会将活动由一个状态迁移到另一个状态。对于数据驱动工作流,活动则根据数据相关的信息执行。因此,在设计工作流组件时,第一步是要理解您必须支持的工作流风格。
(P124)
你可以使用代码、标记语言或代码和标记语言组合的方式来编写工作流。采用何种方式取决于您解决方案编写模式的需求。
WF 提供了以开发人员为中心的解决方案,用于创建顺序、状态机以及数据驱动工作流。它支持纯代码、代码分离及标记编写模式。
(P125)
BizTalk 支持顺序、状态机和数据驱动工作流,以及代码分离和标记编写模式。
(P126)
微软企业服务总线 (ESB) 工具包扩展了 BizTalk 的功能,它关注的是如何构建始终连接的、面向服务的应用程序。
【第15章】 【设计数据组件】
(P129)
数据层组件包含数据访问组件和服务代理组件,其中数据访问组件用于访问系统边界内承载数据,服务代理组件提供访问其后端系统通过 Web 服务暴露数据。
(P130)
数据层应该利用数据访问基础结构统筹所有的数据源连接。
(P131)
不管是加密还是明文,都不要在数据库中保存用户密码以供今后验证。您应该是保存使用了盐值 (为哈希的值指定一个随机的字节) 哈希后的密码。
【第16章】 【质量特性】
(P135)
应用程序处理诸如可用性、性能、可靠性及安全性等质量特性的优劣程度反映了设计是否成功及软件应用程序的整体质量。
每个系统对于每一个质量特性的重视程度和优先级都不尽相同。
(P139)
延迟指的是响应任何事件之前的事件。
吞吐量指的是一定时间之内发生的事件数量。
应用程序的性能会直接影响其可伸缩性,并且缺乏可伸缩性也会影响性能。
(P141)
可伸缩性是在不影响系统性能的情况下处理额外负载的能力,或是增加负载量的能力。有两种方式可提高可伸缩性 : 纵向伸缩 (向上扩展) 和 横向伸缩 (向外扩展) 。如果需要进行纵向伸缩,那么需要为单个机器增加诸如 CPU 、 内存及磁盘之类的资源。如果需要实现横向伸缩,那么需要为运行应用程序的农场增加更多机器来共享负载。
【第17章】 【横切关注点】
(P148)
在跨物理边界或进程边界的时候考虑使用基于消息的通信,在进程内 (只跨越逻辑边界) 考虑使用基于对象的通信。
消息队列可以进行事务性消息递送及支持可靠的只发一次的递送。
(P151)
应该尽量让缓存的数据靠近使用缓存的地方,这样可以减少处理和网络往返过程,并且可以最大化性能和应用程序响应速度。
【第18章】 【通信和消息】
(P161)
为组件解耦不仅仅可以增进可维护性,而且可以提高灵活性,使得可以在将来更方便改变部署策略。
由于每一次跨逻辑或物理边界的通信都会增加处理开销,因此需要通过减少往返和最小化在网络上传输的数据量等方式来设计高效的通信。
(P162)
如果需要和其他系统进行互操作,则考虑使用 XML 序列化。但是要始终记住 XML 序列化会带来更多的性能开销。如果性能至关重要,那么可以考虑使用二级制序列化,因为它更快,并且序列化后的数据也比 XML 序列化后的数据更小。
(P165)
考虑使用 DTO 来作为数据传递的一个单元,而不是每一次都传递独立的数据类型。
【第19章】 【物理层和部署】
(P169)
对于非分布式部署,除了数据存储功能之外的所有的功能和层都在一个服务器中。
(P170)
对于分布式部署,应用程序的各层位于独立的物理层。这种分层机制将系统的基础结构组织成一组物理层的方式,通过这种方式可以针对特定运营需求和系统资源的使用情况对特定服务器环境进行分别优化。
您需要谨记 : 增加更多的物理层也就增加了复杂度、部署工作量和成本。
您可以利用异步调用、单向调用或消息队列等技术来减少跨物理边界调用时的阻塞。
(P171)
在设计分布式环境的时候,必须确定哪些逻辑层和组件会放到哪一个物理层中。大多数情况下,会把表现层放在客户端或 Web 服务器上;服务、业务和数据层放在应用服务器上;数据库则放在单独的服务器上。
确定在分布式环境中如何部署组件时,可以考虑如下指导原则 :
-
只在必要时将组件分布式部署。实现分布式部署的常见原因包括安全策略、物理约束、共享业务逻辑和可伸缩性;
-
如果表现组件需要同步使用业务组件,那么可以把业务组件和表现组件部署在相同的物理层中,以最大化性能及简化运营管理;
-
如果出于安全性考虑,需要表现组件和业务组件之间具有信任边界,那么可以把它们部署在不同的物理层中;
-
除非出于安全性考虑,需要服务代理组件和调用服务代理的组件之间具有信任边界,否则可以考虑将它们放在同一个物理层中;
-
尽可能让异步调用的业务组件和工作流组件部署在相同的独立的物理层中;
- 把业务实体和使用业务实体的组件放在相同物理层中;
(P172)
如果您正在开发一个需要访问应用服务器的客户端程序,或正在开发一个会访问独立数据库服务器的单机客户端程序,那么您可以考虑两层模式。
(P173)
对于三层设计,客户端会和部署在独立服务器上的应用软件进行交互,而应用服务器又会和位于另一个服务器上的数据库进行交互。对于大多数 Web 应用程序服务来说,这是最常见的部署模式,而且也能满足大多数一般的应用的需要。您可能会在客户端和 Web / App 层之间实现防火墙,在 Web / App 层和数据库之间又实现一道防火墙。
如果安全需求规定业务逻辑不能部署在边缘网络中,或是应用程序代码需要使用大量服务器资源,您希望把相关功能的负载转移到其他服务器,那么您可以考虑四层模式。
如果出于安全方面的考虑,不能把业务逻辑放在前端 Web 服务器上,那么可以考虑为 Web 应用程序使用分布式部署。可以为业务层使用基于消息的接口,并且考虑使用二进制编码的 TCP 协议来和应用层进行通信,以获得最佳性能。还应该考虑使用负载均衡来分发请求,这样可由不同的 Web 服务器来处理请求,并且要考虑在设计可伸缩 Web 应用程序时避免服务器亲和性,为 Web 应用程序设计无状态的组件。
(P174)
对于 N 层部署,您可以把表现和业务逻辑放在客户端,或只把表现逻辑放在客户端。
“纵向扩展”就是升级正在运行的硬件,而“横向扩展”则是通过把应用程序分发到多个物理器上来分担负载。如果打算横向扩展,一般会使用负载均衡策略,即负载均衡集群。
(P175)
负载均衡通过把客户端的请求分发到多个服务器,扩展了基于服务器程序的性能,比如 Web 服务器。负载均衡技术一般指负载均衡器,接收请求,然后在必要时将其转发至某个主机。负载均衡主机并发响应不同的客户端请求,即使多个请求来自相同客户端。
根据路由技术,负载均衡器可能会检测到无效的 Web 服务器,然后把它从路由列表中移除,这样可以将失败带来的影响降到最低。
如果每一个客户端请求之间不需要进行跟踪也不需要保存信息,换句话说通信是无状态的,那么负载均衡集群是最具伸缩性也是最有效率的。如果必须跟踪状态,那么可能需要使用亲和性技术和会话技术。
(P176)
在开发过程中,如果使用 Internet 信息服务 (IIS) 6.0 或以上的版本,可以配置 IIS 为 Web 园模式,帮助确保开发的应用程序正确处理了会话状态。
Web 服务器、 Web 农场一样,如果业务层、数据层和表现层没有位于相同的物理层上,可以通过应用农场的方式来横向扩展业务层和数据层。将从表现层过来的请求分发到农场中的每一服务器上,都有差不多的负载。根据每一层的需求及期望用户个数的负载,应将业务层和数据层的组件放到不同的应用农场中。
(P179)
一般情况下,如果打算扩展应用程序,可以从两种基本选择中选择一个或者两个进行组合,这就是“纵向扩展”(让盒子变得更大)和“横向扩展”(用更多的盒子)。
对于“横向扩展”,增加更多服务器并且使用负载均衡和集群的解决方案。除了能处理额外的负载,“横向扩展”应用场景还能缓解硬件故障的问题。
使用额外的处理器和增加内存的纵向扩展是一个经济实惠的解决方案。这种方案还可以避免引入“横向扩展”和使用 Web 农场和集群技术带来的额外成本。应该先考虑“纵向扩展”选项,并且通过性能测试来检查“纵向扩展”方案是否达到了制定的可伸缩性标准,以及是否在某种可接受的性能范围内能支持必要的并发用户数。
如果由于 CPU 、 I/O 或内存上的瓶颈,为解决方案进行“纵向扩展”不能提供足够伸缩性,那么必须进行“横向扩展”和引入额外的服务器。
(P180)
具有清晰远程接口的松耦合的分层设计,相比紧密耦合的混乱交互的设计,更容易进行“横向扩展”。由于分层设计天生就具有分离点,那么在层的边界进行“横向扩展”就非常适合了。其中的诀窍是找到正确的边界。
【第20章】 【选择应用程序类型】
(P187)
在选择应用程序类型的时候,您需要考虑需求、技术限制,以及最终的用户体验类型。
(P188)
每个应用程序类型都可以使用一种或多种技术来实现。使用场景和技术限制,以及开发组的能力和经验都对技术的选择有影响。
(P191)
RIA 应用程序一般依赖于一个客户端的插件或一个托管的执行环境 (比如 XAML 运行时或 Silverlight) 。这个插件需要和远程的 Web 服务器进行通信, Web 服务器可以生成客户端插件或执行环境所需要的代码和数据。
【第21章】 【设计 Web 应用程序】
(P196)
在设计一个 Web 应用程序时,考虑使用一些技术,比如缓存和输出缓冲来降低浏览器和 Web 服务器之间的来回通信,以及 Web 服务器与其下游服务器之间的通信。一个好的缓存策略可能是一个非常重要的跟性能相关的设计要点。
(P198)
授权决定着一个已经通过认证的身份是否可以执行某个任务,以及是否可以访问某些资源。
您应该使用缓存来优化对引用数据的查找,避免网络往返通信的开销,避免不必要的及重复的提交。
(P200)
尽可能地使用 CSS 来布局,而不要使用基于表格的布局。
基于表格的布局在渲染的时候会慢一些,并且在布局复杂的时候会出现一些问题。
将客户端脚本放在一个独立的脚本文件中,这样做可以被浏览器缓存。
(P201)
对于多服务器 (Web 场) 的场景,并且必须在服务器之间集中存储 Session 数据,那么考虑使用 SQL Server 状态存储。
【第22章】 【设计富客户端应用程序】
(P209)
富客户端的用户界面具有高性能、高交互性以及用户体验丰富的特点,并可适应独立的、连线的、偶尔可连线的以及离线的场景。
(P210)
在设计一个富客户端应用程序的时候,软件架构师的目标就是要选择一项合适的技术,然后通过将任务按不同内容领域进行划分,使得设计出来的结构的复杂度最小。设计必须要在性能、安全、重用性以及易维护性上满足应用程序的需求。
(P215)
有时候,尽管应用程序的其他所有方面都表现得不错,但一个差的用户体验就能产生严重的负面影响。因此将您的应用程序设计成从一开始就提供一种引人注目并直观的用户体验是非常重要的,因为用户体验会被您的应用程序的架构的很多不同方面所影响。
尽可能利用数据绑定功能来显示数据,尤其对于表格式的数据和多行的数据。这样做能缩减所需要的代码,简化开发并减少代码错误。
(P218)
Windows 窗体、 WPF 和 Silverlight 数据绑定都支持双向绑定策略,它允许将数据结构绑定到一个用户界面组件上向用户显示当前的数据,并允许用户修改数据,然后使用用户所输入的值自动更新原来的数据。
【第23章】 【设计富 Internet 应用程序】
(P225)
RIA 在提供了 Web 应用程序在部署和维护性能上所拥有的大部分优点的同时,还支持丰富的图形和流媒体。
【第24章】 【设计移动应用程序】
(P241)
如果要构建富客户端,那么业务层和数据服务层可能会放在设备自身。如果要构建瘦客户端,所有的层都要放在服务器上。
【第25章】 【设计服务应用程序】
(P255)
“服务”是指能提供一组功能的公共接口。
【第26章】 【设计托管和云服务】
(P270)
基于云的服务通常分为几种类型,例如 存储/计算,业务服务以及 零售/批发 服务。
【第27章】 【设计 Office 业务应用程序】
(P287)
OBA 是一种企业整合应用程序。
OBA 在设计上是通过使用开放的标准、标准的文件格式和 Web 服务来进行协作。
【第28章】 【设计 SharePoint LOB 应用程序】
(P301)
SharePoint LOB 应用程序可以被配置成通过网站的形式来发布面向 Internet 的内容,这样网站就可以与 Web 场的部署一起向外扩展以支持大量用户的访问,它还可以与 ASP.NET 集成在一起,利用这些网站来显示 LOB 数据。
**