“高内聚”与“低耦合”为什么是互相排斥的软件设计原则?

α、背景

软件架构设计中常常被提到的“高内聚”和“低耦合”设计原则是两个相互关联但又看似矛盾的设计原则,它们分别描述了软件模块内部的组织方式以及模块之间的交互关系。那么又为什么说这两个原则在本质上具有互相排斥的特性呢?

此图片来源于网络 

β、高内聚?

内聚是指一个软件模块内部各组成部分(如函数、方法、数据等)之间相互关联的程度,衡量的是这些部分对于共同完成单一职责或紧密相关功能的集中程度。

高内聚意味着一个模块应包含那些密切相关的功能和数据,这些功能和数据紧密协作以实现模块的核心职责。高内聚模块的特点包括:

(1)模块内的所有元素都是为了支持同一个目标或完成同一类任务。

(2)模块内部逻辑清晰,职责明确,易于理解和维护。

(3)更少的外部依赖,因为大部分工作都在模块内部完成。

γ、低耦合?

耦合是指不同软件模块之间相互依赖的紧密程度,即一个模块改动时对其他模块造成影响的程度。

低耦合意味着模块之间的相互依赖应该尽可能地减少,每个模块应保持相对独立,对外提供清晰、稳定的接口,而不是暴露其内部实现细节。低耦合模块的特点包括:

(1)模块间通过定义良好的接口进行交互,接口的变化不会直接影响到模块内部。

(2)模块可以独立开发、测试、部署和替换,而不影响整个系统的稳定性和功能。

(3)修改一个模块时,对其它模块的影响小,有利于系统的扩展和维护。

δ、相互排斥?

尽管高内聚和低耦合都是为了提高软件的可读性、可维护性、可扩展性和可重用性,但它们在设计上的追求似乎存在一定的对立:

职责划分的边界问题

高内聚要求将紧密相关的功能集中在一个模块内,这可能导致模块内部功能复杂度增加,为了实现这一复杂功能,模块可能会需要访问或操作其他模块的数据,从而增加了模块间的耦合。

反之,若过分强调低耦合,可能会将一些本应紧密协作的功能分散到多个模块中,导致模块内部职责不集中,反而降低了内聚性。

依赖关系的处理

高内聚模块倾向于封装更多的内部细节,这可能需要其他模块更深入地了解其内部运作机制,或者依赖其内部状态,从而增加了耦合。

而为了实现低耦合,需要尽量减少模块间共享状态和直接访问对方内部数据的情况,这可能需要将原本可以在一个模块内完成的操作分散到多个模块中,影响内聚性。

设计决策的权衡

在实际设计过程中,往往需要在内聚性和耦合度之间做出取舍。过于追求高内聚可能导致模块过于庞大、复杂,难以复用,而过度追求低耦合可能导致系统过于分散,增加通信开销,且不易理解整体功能流。设计者必须在保持模块内部逻辑紧凑、职责明确(高内聚)与保持模块间相互独立、互不影响(低耦合)之间找到平衡点。

总之,高内聚强调模块内部的紧密协作与专注单一职责,而低耦合关注模块间的独立性和解耦。在追求其中一个目标的过程中,如果不加注意,可能会对另一个目标产生负面影响,因此在软件架构设计中,高内聚和低耦合确实呈现出一种互相排斥的本质。优秀的软件设计需要通过合理的抽象、接口定义、模块划分等手段,在两者之间找到最佳实践,使得软件既具有清晰的内部结构,又能够灵活地与其他模块协同工作。

ε、解决矛盾?

SOLID原则、组合复用原则和迪米特法则(最少知识原则)是一组用于指导面向对象设计和实现的原则,旨在帮助我们构建出高内聚、低耦合的软件模块。这些原则有助于解决高内聚与低耦合之间的矛盾,并提升代码的可读性、可维护性、可扩展性和可复用性。下面分别简要介绍这七个原则:

SOLID原则:

  1. 单一职责原则 (Single Responsibility Principle, SRP):一个类(或模块)应该只有一个引起它变化的原因。这意味着一个类只负责一项核心职责,避免承担过多的功能,确保了高内聚。

  2. 开闭原则 (Open-Closed Principle, OCP):软件实体(如类、模块、函数等)应当对扩展开放,对修改关闭。即允许在不修改现有代码的基础上添加新功能,降低模块间的耦合。

  3. 里氏替换原则 (Liskov Substitution Principle, LSP):子类型必须能够替换掉它们的基类型。这意味着子类应保持父类的行为约定,确保继承体系的稳定性,降低模块间的耦合。

  4. 接口隔离原则 (Interface Segregation Principle, ISP):客户端不应该被迫依赖它不需要的接口。应将大而全的接口拆分为更小、更具体的接口,使客户端仅依赖于所需的方法,提高内聚性并降低耦合。

  5. 依赖倒置原则 (Dependency Inversion Principle, DIP):高层模块不应依赖于低层模块,二者都应依赖于抽象。具体而言,应依赖于抽象接口而非具体实现,这样在更换具体实现时,高层模块不受影响,增强了系统的可扩展性和低耦合性。

组合复用原则:

尽量使用对象组合而非类继承来达到复用的目的。组合能更好地保持对象的独立性,避免因继承而导致的过深的继承链和不必要的耦合,同时鼓励高内聚的设计。

迪米特法则(最少知识原则):

一个对象应当对其他对象有最少的了解。也就是说,一个对象只和其直接的朋友(与之交互的对象)交流,不和陌生人(非直接朋友)交流。这样可以限制模块间的直接交互,降低耦合,增强内聚性。

遵循以上原则进行模块功能划分设计,可以帮助我们在高内聚和低耦合之间找到平衡,构建出易于理解、维护和扩展的软件系统。在实际应用中,应根据具体项目需求和场景灵活运用这些原则,避免教条化。

ζ、设计与管理?

软件架构设计不仅是一项技术活动,它同时也对参与其中的人员,特别是软件架构师,提出了较高的管理和经营要求。以下几点解释了为何进行软件架构设计有助于培养人的管理经营能力:

  1. 资源规划与成本控制:架构设计涉及到对系统组件、技术选型、人力资源、开发周期等方面的规划与决策,这些决策直接影响项目的成本投入。架构师需要考虑如何在有限的预算和时间内,合理分配资源,选择高效的技术方案,这与企业经营管理中的成本控制、资源配置等理念高度契合。

  2. 风险管理与决策制定:架构设计需要预见潜在的技术风险、业务变更风险等,并制定应对策略。架构师需要评估各种设计方案的优缺点、潜在问题及其对项目整体的影响,然后做出最优决策。这种前瞻性的风险识别、评估和决策过程,与企业管理中对市场风险、运营风险的管理类似,锻炼了架构师的战略思维和决策能力。

  3. 团队协作与沟通协调:架构设计并非孤立工作,而是需要与业务方、开发团队、运维团队、第三方供应商等多个利益相关者进行有效沟通,协调各方需求与期望,达成共识。架构师必须具备良好的沟通技巧、谈判能力和团队协作精神,这与企业管理中的团队建设、跨部门协调、供应链管理等职责相通。

  4. 战略视野与业务理解:架构设计不仅要解决眼前的技术问题,更要考虑系统未来的扩展性、适应性以及对业务发展的支撑能力。架构师需要深入理解业务逻辑、行业趋势、市场竞争格局等,以便设计出既能满足当前需求又能适应未来变化的架构。这种长远视角和对业务的深刻洞察,与企业经营者需要具备的战略规划能力相呼应。

  5. 技术领导与创新推动:架构师通常扮演技术领导者的角色,他们需要引领团队采用新技术、新方法,推动技术创新和落地,以提升系统的竞争力。这种推动变革、激发创新的能力,同样是优秀企业管理者必备的素质。

  6. 标准化与流程优化:架构设计过程中,架构师会制定技术标准、编码规范、接口协议等,以保证系统的统一性和一致性。此外,还会设计和优化开发、测试、部署等流程,提高团队工作效率。这些工作与企业管理中的标准化建设、流程改进、效率提升等管理实践紧密相关。

综上所述,软件架构设计过程中涉及的资源规划、风险管理、团队协作、战略视野、技术领导、标准化与流程优化等工作,与企业的管理经营有着诸多相似之处。通过实践软件架构设计,参与者能够在技术层面之外,不断提升自身的管理意识、决策能力、协调技巧、创新思维等软实力,这些能力不仅对软件项目成功至关重要,也对个人在更广泛的职业领域,尤其是管理岗位的发展大有裨益。因此,可以说进行软件架构设计是在培养人的管理经营能力。

此图片来源网络 

  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

初心不忘产学研

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值