原著名称《.NET Application Architecture Guide,2nd Edition》,应该可以从微软的官网下载到,是微软的模式与实践小组的大作。Patterns & Practices在http://www.codeplex.com/上面有很多的好作品,其实.NET平台也有很好的开源项目,也有很广的选择面,只是这些不像java那么开放,.NET的开源是微软主导的。
下载地址:patterns & practices: Application Architecture Guide 2.0
回到主题
软件架构经常被描述成系统的组织或者是结构,系统代表完成特殊功能,或者是一系列功能的组件集合。换句话说,架构也就是将组件组织起来,支持特定的功能。
下图展示了常用的应用架构
除了组件分组,其它的就是组件之间的交互,以及不同的组件如何在一起工作。
关键的设计原则
在开始设计之前,思考一下关键的原则,将会帮助你创建一个最小花费、高可用性和扩展性的架构。
- 分离关注点,将应用划分为在功能上尽可能不重复的功能点。主要的参考因素就是最小化交互,高内聚、低耦合。但是,错误的分离功能边界,可能会导致功能之间的高耦合性和复杂性,
- 职责单一,每一个组件或者是模块应该只有一个职责或者是功能,功能要内聚。
- 最小知识原则,一个组件或者是对象不应该知道其他组件或者对象的内部实现细节。
- 不要重复你自己,你只需要在一个地方描述目的。例如,特殊的功能只能在一个组件中实现,在其他的组件中不应该有副本。
- 最小化预先设计,只设计必须的内容。在一些情况,你可能需要预先设计一些内容。另外一些情况,尤其对于敏捷开发,你可以避免设计过度。如果你的应用需求是不清晰的,最好不要做大量的预先设计。
当设计一个应用和系统的时候,软件架构的目的是通过将设计分离到不同的关注点,来最小化复杂性。例如,用户接口UI,业务处理Business Process,数据访问Data Access就代表不同的关注点。在每个关注点内部,你设计的组件应该集中的内部实现,不应该和其他的组件混淆代码。例如,UI处理组件不应该包括直接访问数据源的代码,相反,应该使用业务组件或者是数据访问组建获取数据。
但是,你还是要为你的应用做一个投入|产出决定。在某些情况,你可能需要简化结构。例如,UI直接绑定到一个结果集。通常,也要从业务的角度考虑功能的边界。下面的这些高层次的原则将会帮助你从更广的范围上考虑影响设计、实现、部署、测试和维护系统的因素。
设计
- 在每一层保持设计模式的一致性。在一个逻辑层的内部,组件的设计对于特殊的功能应该保持一致性。
- 不要在应用中复制功能。只能在一个组件中提供指定的功能,这个功能不能在其他组件中复制。这将会保持组件的内聚性,而且如果功能需要修改的话,会变得很容易。
- 组合优先于继承。无论在什么地方,如果需要重用代码的话,优先使用组合而不是继承,因为继承增加了父类和子类的依赖关系,限制了子类的重用,
- 为开发建立代码风格和命名空间。建立统一的代码风格,使用和组织有关系的有意义的命名空间。
- 在开发的过程中,使用QA来保证系统的质量。在开发的过程中,使用单元测试和其他QA技术,例如,依赖分析和静态代码分析。为组建和子系统定义清晰的行为和性能指标,使用自动化QA工具来保证不影响整个系统的质量。
应用分层
- 分离关注点。将应用分离为不同的功能,这些功能保持尽可能小的重叠。主要的好处是一个功能可以最小化和其他功能的依赖关系。另外,如果一个功能失败了,不会导致其他功能的失败,对于其他功能来说是独立的。使得应用更容易理解和设计,简化复杂系统的管理。
- 明确层之间是如何通信的。
- 使用抽象实现层之间的松散耦合。可以通过定义接口来实现。另外,还可以通过使用接口类型或者是基类定义常用的接口。
- 在同一层,不要混合不同类型的组件。例如,UI层不应该包含业务处理组件,相反,应该包含处理用户输入和处理用户请求的组件。
- 在层和组件内部保持数据格式的一致性。混乱的数据格式,将会导致系统更难实现、扩展和维护。
组件、模块和功能
- 一个组件和对象不应该依赖于其他组件的内部实现细节。
- 组件的功能不要超出范围。例如,UI处理组件不应该包含数据访问代码,或者是试图提供其他的功能。
- 理解组件之间是如何通信的。这需要理解应用一定要支持的部署方案。你一定要决定是否所有的组件都运行在同一个进程中?是否一定要支持跨越物理或者是进程边界的通信?还是实现消息为基础的接口?
- 为组件定义一个清晰的职责。
你还要考虑下面的这些横向的关注点:
- 日志
- 认证
- 授权
- 异常管理
- 通信。选择合适的协议,最小化网络的通信量,在网络上保护传递的敏感信息。
- 缓存。为了提高系统的性能和响应速度,需要确定什么应该缓存?缓存在哪里?设计缓存的时候,要考虑到web服务器场和应用服务器场的问题。