概览
这章描述业务层的设计过程,包含了设计业务层和业务组件是重要的原则。这些原则被分成不同的种类,包括设计业务层和实现合适的功能,如Security,Caching,Exception
Management,Logging,Validation. 这些代表了商业层设计时容易发生错误的主要区域。
下面的列表解释了业务层包含的主要组件角色和任务:
应用程式Facade. (可选). 应用程序门面合并了多种业务操作到一个基于消息的操作。你可以从表示层使用不同的通信技术来访问应用程式门面。
业务组件。当用户进程收集了需要的数据后,就是使用业务规则来处理。规则会描述数据怎么被操作以及转变。规则也许简单或者复杂,由它本身业务决定。当业务需求演变后,规则跟着被更新。
业务实体组件。业务实体被用来在组件中传送数据。数据代表了真实世界的业务实体,如产品或者订单。应用程序内使用的业务实体结构有DataSet,可标记语言(XML)流。同样,他们也可以用自定义的面向对象的类来代表真实世界的实体,如产品或者订单类。
业务工作流。许多业务流程包含了多个步骤,必须在正确的命令下才能执行。业务工作流定义和协调了长时间运行,多步的业务流程,可以使用流程管理工作来实现。
方法
当设计业务层时,你必须考虑业务层的构成,如业务组件,业务实体和业务工作流组件。这节简要的介绍了设计业务层各组件的方式。
业务层。当设计业务层,你需要考虑以下几点:
确认业务层调用者。
确定怎么暴露业务层接口。
确定业务层的安全要求。
确定业务层的验证要求和策略。
确定业务层的缓存策略。
确定业务层的异常管理策略。
业务组件。当设计业务组件时,你需要考虑以下几点:
确认应用程序要是使用的业务组件。
对业务层的位置,耦合以及交互作出主要决定。
选择合适的事务支持。
确认你的业务规则处理方式。
确认适合需求的模式。
业务实体。当设计业务实体时,你需要考虑以下几点:
确认业务实体的统一数据格式。
选择数据格式。
可以选择性的设计自己的自定义对象。
可选择确定你需要的串行化支持。
业务工作流。当设计业务工作流时,你需要考虑以下几点:
确认工作流适用的场景。
选择一个授权模式。
确定规则的处理方式。
选择一个工作流解决方案。
设计业务组件以支持工作流。
设计注意事项
当设计业务层时,软件架构的目标是通过分离任务到不同的关注区域以减少复杂性。例如,业务处理,业务工作流,以及业务实体都代表了不同的关注区域。对于每一个区域,你设计的组件需要专注于特定的区域以及不能有代码关联到其它区域。
当设计业务层时,需要遵循以下原则:
决定你是否需要一个单独的业务层。尽可能的使用一个单独的业务层可以提高应用程式的可维护性。
确定业务层的责任。用业务层来处理复杂的业务规则,传送数据,应用策略,以及验证。
在业务层不要混合不同类型的组件。用业务层使业务逻辑和表现层及数据访问层解耦,并且简化业务逻辑测试。
重用通用的业务逻辑。使用业务层以集中通用的业务逻辑功能和提高重用。
确认业务层的调用者。这可以帮助你确认业务层的暴露方式。例如,如果你的表现层和一个外部程式需要使用业务层,你可能要选择暴露你的业务层通过WebService。
当访问一个远程业务层时要减少数据往返。如果你使用基于消息的接口,考虑使用粗粒度的数据包,比如DTO。另外,考虑为业务层实现一个远程的FACADE。
避免层之间的紧耦合。当创建业务层接口时使用抽象。可以使用公共对象接口,通用接口定义,抽象类,或消息来实现抽象。对于WEB程式,考虑在表示层和业务层之间使用消息接口。
业务层框架
Category |
Common Issues |
Authentication |
在需要的地方使用验证。 |
|
设计自定义的验证机制。 |
|
在合适的时候使用单点登录。 |
Authorization |
使用了不正确的角色粒度。 |
|
在不需要的时候使用了匿名和代理。 |
|
授权代码和业务处理代码混合。 |
Business Components |
使用了不相关的功能重载了业务组件。 |
|
在业务组件里混合了数据访问逻辑和业务逻辑。 |
|
没有考虑使用基于消息的接口以暴露业务组件。 |
Business Entities |
在不合适的地方使用了域模型。 |
|
为你的业务实体选择了不正确的数据格式。 |
|
没有考虑串行化支持。 |
Caching |
缓存了易变的数据。 |
|
在业务层缓存了过多的数据。 |
|
没有在ready-to-use的时候缓存数据。 |
|
在没有加密的窗体缓存了敏感数据。 |
Coupling and Cohesion(耦合和衔接) |
层之间紧耦合。 |
|
没有明确分离业务层关注点。 |
|
在层之间没有使用基于消息的接口。 |
Concurrency and Transactions(并发和事务) |
没有提供对可写的静态数据的并发访问。 |
|
没有选择正确的数据并发模型。 |
|
使用了长时间运行的事务锁住了数据。 |
Data Access |
从业务层直接访问了数据库。 |
|
在业务组件里混合了数据访问逻辑和业务逻辑。 |
Exception Management |
对于终端用户显示了敏感信息。 |
|
要为应用逻辑使用异常。 |
|
没有记录重要异常的详细信息。 |
Logging and Instrumentation |
对业务组件没有使用适当的监控。 |
|
没有Log致命的系统和业务事件。 |
|
没有处理记录失败的情况。 |
Service Interface |
破坏了服务接口。 |
|
在业务接口实现了业务规则。 |
|
没有考虑互操作需要。 |
Validation |
依赖于表现层的验证。 |
|
没有验证参数的各个方面,比如范围,类型以及格式。 |
|
没有重用验证逻辑。 |
Workflows |
没有考虑程式管理的需要。 |
|
选择了不正确的工作流模式。 |
|
没有考虑处理所有的异常状态。 |
|
选择了不正确的工作流技术。 |
验证
设计一个业务层有效的验证策略对系统的安全性和可靠性很重要。没有设计一个好的验证策略会使你的应用程式易受欺骗攻击,字典攻击,会话劫持和其它类型的攻击。
当设计验证策略时,考虑以下原则:
如果业务层和表现层互相信任,并且位于同一个层里,那么在业务层不要使用验证。
如果业务层部署在单独的层里或者被其它应用程式共享,请使用用户验证。
如果你的业务层被多个程式调用并且位于一个信任的环境里,请实现单点登录机制。
决定你的业务层是否需要遵循调用者的标识。
使用信任的子系统去访问后台服务以加大数据连接池的应用。
避免设计自定义的验证机制。
如果使用WebService,考虑使用IP过滤以显示来自表示层的调用。
授权
设计一个业务层有效的授权策略对系统的安全性和可靠性很重要。没有设计一个好的授权策略会使你的应用程式易受信息披露,数据篡改,以及权限提升。
当设计授权策略时,请遵循以下原则:
访问不同层级的粒度时请使用角色控制。
对使用自己的身份,账户组或角色的调用者使用授权以保护资源。
对于业务决策使用基于角色的授权。
对于系统审核使用基于资源的授权。
当使用混合了身份,角色,许可,权力以及其它因素的联合授权时,考虑使用基于债权(claims-based)授权。
避免使用匿名和代理,因为它会显著的影响性能和伸缩性。通常一个匿名客户端的调用比直接调用代价高的多。
避免在业务处理代码中混合授权代码。
业务组件
业务组件用不同的模式实现业务规则,接收以及返回单个或复杂的数据结构。你的业务组件应该暴露需要执行的服务,而对数据存储不可知。编写业务组件注意要有意义以及保持事务的一致性。设计业务组件是一个重要的工作。如果业务组件设计的不合理,那代码则很难维护。
当设计业务组件时,遵循以下原则:
避免加载不相关的组件或混合功能。想
避免混合数据访问逻辑和业务逻辑。
设计组件要高聚合。
考虑使用基于消息的通信来调用业务组件。
通过服务接口来暴露进程。
保证业务组件的输入和输出数据是一致的。
将服务功能暴露,而对数据存储不可知。要使用松耦合的设计。
考虑使用业务流程组件来实现业务规则。
如果程式中的业务规则经常改变,则将规则存储在一个业务引擎里。
如果业务流程涉及多个步骤以及长时间运行的事务,考虑使用工作流组件。
对组件的各个组成部分实现高效和合适的管理。
业务实体
业务实体存储数据值并且通过属性来访问;他们提供有状态的编程方式去访问业务实体以及相关的功能。因此,设计或选择合适的业务实体对于提高性能和业务层效率是至关重要的。
当设计业务层实体时,考虑以下原则:
在不合适的地方避免为业务实体使用域模型模式(Domain Object, 系统的核心业务对象)。
为你的业务实体选择合适的数据格式。
为你的业务实体考虑串行化需求。
使用轻量级的域对象(Domain Object)来呈现业务实体。
如果数据库中的表代表了业务实体,考虑使用Table Module模式。
尽量减少物理层间的调用。例如,使用DTO对象。
缓存
设计合适的缓存策略对于提高程式业务层的性能和响应非常重要。使用缓存来优化数据查找,避免网络数据包往返,避免不必要的和重复的处理。作为缓存策略的一部分,你必须决定什么时候并且怎样来加载缓存数据。为避免客户端延迟,使用异步加载数据方式或者使用批处理。
当设计缓存策略时,考虑以下原则:
评估业务层缓存的数量规模。过度的缓存会引起反作用。
在业务层缓存静态数据可以经常的被重用。
缓存数据可以不通过数据库来快速和有效率的检索。
在业务层使用Ready-to-use 缓存数据。
如果可能的话,避免缓存敏感的数据,或者在缓存里设计一个机制以保护敏感数据。
考虑Web怎样部署会影响你的业务层缓存方案。
耦合以及内聚
当设计业务层组件的时候,保证他们都是高内聚,并且层间低耦合。这有助于帮助提高程式的可伸缩性。
当设计耦合和内聚时,遵守以下规则:
在层之间避免紧耦合。业务层只需要知道它以下的层(数据层),而不需要知道以上的层(表现层或访问业务层的外部程式)。
对业务层使用基于消息的接口。
业务层组件要高内聚。
避免在业务层组件中混合业务逻辑和数据访问逻辑。
并发和事务
设计并发和事务时,选择合适的并发模型和决定管理事务的方式非常重要。你可以在乐观的模型和悲观的模型之间(an
optimistic model and a pessimistic model)选择并发模型。
当设计并发和事务时,考虑以下原则:
如果在操作重要的业务,考虑使用事务。
当访问单一的数据源时使用基于连接的事务。
注意事务的边界。
在不能使用事务的地方可以使用compensating方法将数据回复到以前状态。
避免长时间保持锁状态。
考虑你是否要使用optimistic or pessimistic locking。
选择合适的事务隔离级别。
数据访问
为业务层设计一个有效的数据访问策略对于维护以及分离关注点非常重要?
当设计数据访问层策略,考虑以下原则:
避免在业务层组件中混合数据访问代码和业务逻辑。
避免在业务层中直接访问数据库。
考虑使用单独的数据层来访问数据库。
异常管理
设计有效的异常管理方案对于业务层的安全性和可靠度非常重要。如果不考虑这些的话你可能会使用程序至于DoS攻击或者暴露敏感信息。产生以及处理异常是昂贵的操作,要考虑性能的影响。
当设计异常管理策略时,考虑以下原则:
不要使用异常来控制业务逻辑。
区分对待边界异常和内部异常。
考虑是否需要在边界间传递异常。
用统一的方法处理边界异常。
设计合适的异常产生策略。
为不能处理的异常设置策略。
设置合适的异常log策略。
设置合适的紧急错误和异常通知策略。
不允许异常暴露敏感信息。
日志监控
设计好的日志和监控方案对于业务层的安全性和可靠性非常重要。如果不考虑这些的话程序容易遭受抵赖威胁,用户可以抵赖他们的行为。在合法的处理中验证错误做法也需要日志文件。记录资源访问的具体时间以及访问方式,那么审查会更有权威。
当设计日志和监控策略时,考虑以下原则:
统一记录和监控你的业务层。
在业务层中要监控关键业务的事件和紧急系统事件。
在业务层中审核和记录所有访问功能。
不要在日志中存储敏感信息。
保证日志记录失败不会影响正常的业务层功能。
服务接? p> 当设计服务接口,考虑服务粒度和互操作性。
当设计服务接口,考虑以下原则:
设计服务接口,当业务逻辑改变的时候不影响接口。
如果业务逻辑被不同的客户端以不同的方式访问,考虑实现多个服务接口。
根据组件需求考虑实现缓存映射,以及接口类型转化。
不要在服务接口中实现业务规则。
对参数使用标准的格式以最大化不同客户端的兼容性。
设计服务接口时,考虑不同平台之间的互操作性。
使用合适的技术以实现服务。
为服务考虑合适的传输协议及消息格式。
验证
对业务层不使用有效的验证策略,会使你的程式易受跨站脚本攻击,SQL注入攻击,缓冲区溢出,以及其它类型的输入攻击。对于一个有效的输入和恶意的输入并没有完全的定义。
当设计验证策略,考虑以下原则:
当设计验证方案,假设所有的输入都是恶意的。
在业务层所有输入和方法参数使用验证,同样包括表现层。
统一验证方法以重用。
选择合适的验证技术。
限制,拒绝,过滤所有输入。
工作?
当设计工作流组件时,考虑怎样管理工作流以及理解那些选择是否可用非常重要。请考虑以下原则:
在包含多步或长时间处理组件中使用工作流。
选择合适的工作流形式依赖于应用背景。
在工作流内处理错误的条件,暴露适当的异常。
如果组件必须有顺序以及同步的执行特定的步骤集合,考虑使用管道模式。
如果处理程式在任何命令下需要异步执行,考虑使用事件模式。
部署考虑
当部署业务层时,考虑生产环境的性能和安全问题。请考虑以下原则:
将业务层和表现层放置到相同的物理层以提高程式性能。
如果必须支持远程的业务层,考虑使用TCP协议提高性能。
使用IPSec来保护业务层之间的数据物料传输。
使用SSL来保护业务层组件和远程WebService之间的调用。
模式地图
Category |
Relevant Patterns |
Authentication |
Direct
Authentication |
|
Brokered
Authentication |
|
Federated
Authentication (SSO) |
Authorization |
Role Based
Authorization |
|
Resource Based
Authorization |
|
Claims Based
Authorization |
|
Trusted subsystem |
|
Impersonation and
Delegation |
Business Components |
Transaction Script |
|
Work Unit |
|
Command |
|
Application Façade |
|
Chain of
Responsibility |
Business Entities |
Entity Translator |
|
Domain Model |
|
Table Module |
Caching |
Cache Dependency |
Coupling and Cohesion |
Adapter |
|
Dependency Injection |
Concurrency and
Transactions |
Coarse Grained Lock |
|
Implicit Lock |
|
Optimistic Offline
Lock |
|
Pessimistic Offline
Lock |
|
Transaction Script |
|
Capture Transaction
Details |
Exception Management |
Exception Shielding |
Logging and
Instrumentation |
Provider |
Service
Interface |
Service Interface |
|
Service Layer |
|
Façade |
Workflows |
Data-driven workflow |
|
Human workflow |
|
Sequential workflow |
|
State-driven
workflow |
重要模式
程式门面(Facade) – 提供统一的服务层。
责任链 (Chain of Responsibility) – 通过允许多个对象来处理请求以避免请求和发送者紧耦合。
命令(Command) – 在通用的执行接口里将请求处理封装在不同的命令对象里。
依赖注入(Dependency Injection) – 使用基类或接口来定义共享的抽象以及使用它来注入到实例中以和共享的抽象接口交互。
域模型(Domain Model) – 创建Web的互连对象,每一个对象都代表一些有意义的个体,它可能象一个公司那么大或者象一条线或一个命令窗体那么小。
实体转换(Entity Translator) – 实现一个对象以将消息数据类型转换为业务需要 的类型,将响应的业务数据类型转换为输入需要的类型。
门面(Facade) – 对操作集合使用统一的接口以减少系统间的耦合。
服务接口(Service Interface) – 系统使用编程接口来和其它系统交互。
服务层(Service Layer) – 使用单独的层来实现服务接口。
表模块(Table Module) – 创建一个组件在数据库表或视图中处理业务逻辑。
技术考虑
使用Windows工作流以简化工作流开发,自动支持安全,可依靠性,数据交互,广泛的传输和编码选择以及提供内置的持久性及行为追踪。
如果要和非微软系统交互,使用BizTalk Server 2006来执行EDI操作。
只有当业务层被限制只能访问SharePoing站点时使用MOSS。
使用Transaction Scope(System.Transactions)来管理横跨多个数据源的事务。
|