[Z]软件架构设计应该考虑的问题

本文探讨了软件架构设计的基本原则和指导方针,强调了关键点分离、单一责任原则、最少知识原则等,旨在帮助开发者创建可维护性强、易于扩展的系统。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

大梦谁先觉?平生我自知

2012-03-07 14:43

[Z]软件架构设计应该考虑的问题

在开始设计之前,考虑主要的设计原则将有助于找到架构的设计的“最佳方案”,降低成本和维护需要,提高系统的可用性和可扩展性。

基本原则

在开始设计之前,考虑主要的设计原则将有助于找到架构的设计的“最佳方案”,降低成本和维护需要,提高系统的可用性和可扩展性。主要的设计原则如下:

l        关键点的分离    将应用程序分成清楚的不同元素,使功能的重叠尽可能的少。

l        单一责任原则    每一个组件或模块应该只负责唯一一个特定的功能。

l        最少知识原则    一个组件或对象应该不用知道其他组件的内部实现细节,而只要按照彼此的约定调用即可。

l        不要重复自己    一个组件对应提供一个功能,一个功能也只应由一个组件提供。而不能将功能的实现分散到很多其他的组件中去。

l        避免在前期做大量的设计  如果你的需求不是很清楚,或者有设计随时间演变的可能,应当避免在项目前期做大量的设计工作。这一设计原则通常被叫做“BDUF”。

l        多用组合少用继承    在尽可能的情况下,使用组合的方式来重用功能,而不使用继承的方式。因为继承增加了父子类之间的依赖关系,限制了子类的重用。

设计要点

在设计软件或系统时,软件架构的目标就是通过将设计分割为不同的关注领域来降低其复杂性。例如,用户接口、业务进程和数据访问均可视为不同的关注领域。在每个领域内部,组件应专注于其特定的领域,而不应该混合其他领域的代码。例如,UI进程组件不应该包括直接访问数据源的代码,而应该使用其他的业务组件或数据访问组件检索数据。


下面列出了设置应用程序的指导方针:

l        避免在前期做所有的设计  如果系统需求不清楚或存在设计演变的可能,在前期不去做一个完整的设计应该是一个好主意。在项目进程中演化设计应该是一个恰当的方法。

l        分割关注领域    将 应用程序分成清楚的不同元素,使功能的重叠尽可能的少。这种方法的好处是一个特征或功能独立于其他的特征或功能,可以实现最优。还有,如果一个特征失败 了,不会导致其他的特征也失败,它们之间彼此独立运行,互不影响。这种方法也有助于应用程序的设计和理解,便于复杂的互相依赖的系统的管理。

l        每个组件或模块应有单一的责任    每一个组件或模块应该负责实现特定的特征或功能。这可以使组件实现内聚且更容易优化和变更。

l        一个组件或对象不应该依赖其他组件或对象的内部细节    组件或对象调用其他组件或对象的方法,这些被调用的方法应该说明如何去使用它。如果需要,将这些内容放在子组件或其他独立的组件中。这将有助于开发一个具有可维护性和适应性的应用程序。

l        在一个应用程序内部不要复制功能  应该只有一个组件提供特定的功能——这个功能不应该在其他的组件中出现。在一个应用程序中复制功能会使功能的变更很难维护,削弱了程序的条理性,引入了潜在的矛盾。

l        确定应用程序组件的组成部分  实现这一点的最好方法是确定符合你情况的模式,检查这些模式所使用的组件的类型。例如,一个小型的应用程序可能不需要一个业务工作流或者UI进程组件。

l        组织不同类型的组件到各自的逻辑层    在一开始,确定不同的关注领域,然后组织相互关联组件到合适的逻辑层中。

l        保持层间设计模式的一致性    在一个逻辑层中,组件的设计对于一类特定的功能应该是一贯的,有延续性的。例如,如果你选择使用表数据网关的模式创建对象,你就不应该再使用其他的方式来访问数据和初始化业务对象。

l        在同一逻辑层中不应混合不同类型的组件    例如,UI层不应该包含业务进程组件,而应该包括处理用户输入和处理用户请求的组件。

l        确定哪类分层要强制执行  在一个严格的分层系统中,A层中的组件不能调用C层中的组件,它应总是调用层B中的组件。而在一个相对宽松的分层系统中,一个层中的组件可以调用其下层中的组件,而不只是正下层中的组件。在任何情况下,都应该避免对上层的调用和依赖。

l        抽象实现层间的松散耦合  通过定义接口,层内的组件间可以以一种共知的方式彼此进行请求和响应,这样的实现相对比较灵活。另外,你也可以用接口或抽象类来定义公共的接口或者抽取公共的部分(依赖倒置)。

l        一个组件不要承载太多的功能  例如,一个UI进程组件不应该包括数据访问代码。一种常见的违反模式的情况叫做Blob(一团),在这种情况下,基类提供了过多的功能。一个“团”对象通常有很多函数和属性用来提供混合了日志和异常处理的业务功能。由于要处理子功能的各种变体,做复杂的初始化,这类对象通常非常庞大。最终结果是,这种的设计很容易产生错误,而且很难维护。

l        清楚组件间是如何通信的  这首先需要了解你的应用程序是如何部署的。需要明确的是,组件间的通信是否需要跨越物理边界或跨进程,所有组件是否运行在统一进程当中。

l        多用组合少用继承    在尽可能的情况下,使用组合的方式来重用功能,而不使用继承的方式。因为继承增加了父子类之间的依赖关系,限制了子类的重用。这也减少了继承的层级,避免了去处理复杂的层级关系。

l        保持层内或组件内数据格式的一致性    混乱的数据格式会使程序很难运行、扩展和维护。每次你都需要在不同格式间进行转换,执行转换的代码。这样减低了性能,而且没有必要。

l        尽可能的将交叉(横切)代码从业务逻辑中抽象出来  交叉(横切)代码通常涉及到安全性、通信和操作管理(例如,日志和检测)。将这些代码混合到业务逻辑中会导致程序扩展和维护上的困难。修改这些交叉(横切)代码会牵联到所有混合了它们的业务逻辑代码的修改。可以考虑使用框架来实现交叉(横切)的集中处理。

l        命名习惯的统一  看看团队、组织里是否建立了相关的命名规定,如果没有,你应该建立一个公用的命名标准。由此而来的代码的一致性会使团队成员检查代码更容易。这样也更易维护。

l        建立异常处理的标准  例如,应该总是在层的边界捕获异常,不应该在层内捕获异常,除非你可以在层内处理它,也不应该用异常来实现业务逻辑。该标准还应包括错误提示、记录日志的策略和对异常的检测

架构框架

下面的表格列出了你在设计架构时应该考虑的主要方面。通过这些关键的问题了解通常会犯错的地方。这个章节为这些不同的方面提供了指导。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值