解锁软件设计的奥秘:《软件设计的哲学》深度解读
创作时间:
作者:
@小白创作中心
解锁软件设计的奥秘:《软件设计的哲学》深度解读
引用
CSDN
1.
https://blog.csdn.net/arong_xu/article/details/145601510
《软件设计的哲学》一书由John Ousterhout撰写,深入探讨了软件设计中的复杂性问题,并提出了一系列设计原则和实践指导,旨在帮助开发者减少软件复杂性,提高代码的可维护性和可扩展性。
这本书的作者John Ousterhout是业界知名专家,拥有丰富的编程经验,参与过众多大型项目,如创建Tcl脚本语言,在分布式操作系统和存储系统领域也取得了显著成就。正是这些宝贵的经验,让他在书中分享的见解深刻又实用。
书籍要点
1. 复杂性的定义与表现
书中开篇就点明,复杂性是软件设计的头号难题。它就像软件里的"暗物质",看不见摸不着,却处处影响着软件开发的效率和质量。
- 复杂性的定义:只要是跟软件系统结构相关,让系统难以理解和修改的东西,都是复杂性的表现。
- 复杂性的表现:
- 变更放大:简单的修改需要多处代码改动
- 认知负荷:开发者需要掌握大量信息才能完成任务
- 未知的未知:不清楚哪些代码需要修改或需要哪些信息
- 复杂性的原因:复杂性主要由依赖关系和模糊性引起。依赖关系是指代码之间的相互依赖,模糊性是指重要信息不明确或难以理解。
2. 战略编程 VS 战术编程
- 战术编程:以快速完成任务为目标,通常会导致代码质量下降,复杂性逐渐积累。战术编程只盯着眼前功能实现,不管以后的事,这样会让系统越来越复杂。
- 战略编程:注重长期代码质量,通过投资时间来改进设计,减少复杂性。战略编程的核心思想是“代码只是能运行还不够”,开发者应优先考虑系统的长期结构,而不是仅仅完成当前任务。
作者建议我们在开发过程中,要不断地做小投资来优化设计,比如花 10% - 20%的开发时间来思考设计问题,这样既能保证项目进度,又能提升软件质量。
3. 模块设计
- 模块化设计:将系统分解为相对独立的模块,每个模块有明确的接口和实现。模块的接口应尽可能简单,隐藏复杂的实现细节。
- 深度模块:深度模块是指功能强大但接口简单的模块。深度模块通过隐藏复杂性,减少了系统的整体复杂性。
- 浅模块:浅模块是指接口复杂但功能有限的模块,通常会增加系统的复杂性。
对于一个模块来说:接口(Interface)越少越好;功能(Functionality)越多越好。
4. 信息隐藏与泄漏
- 信息隐藏:模块应隐藏其内部实现细节,只暴露必要的接口。信息隐藏可以减少依赖关系,简化接口。
- 信息泄漏:当设计决策在多个模块中反映时,会导致信息泄漏,增加系统的复杂性。应尽量避免信息泄漏,确保每个模块只负责特定的功能。
5. 通用模块 vs. 专用模块
- 通用模块:通用模块的接口应设计得足够通用,能够适应多种使用场景。通用模块通常比专用模块更简单,更易于维护。
- 专用模块:专用模块的接口通常与特定功能紧密耦合,容易导致信息泄漏和复杂性增加。
6. 不同层次的抽象
- 不同层次的抽象:系统中的每一层应提供不同的抽象,避免相邻层次的抽象过于相似。如果相邻层次的抽象相似,通常意味着模块分解存在问题。
- 传递方法:传递方法是指只调用其他方法而不做任何额外工作的方法,通常表明模块的职责划分不清晰。
7. 将复杂性向下推
- 将复杂性向下推:模块应尽可能处理内部的复杂性,而不是将复杂性暴露给使用者。模块的接口应尽可能简单,即使这意味着模块的实现会变得更复杂。
8. 代码的合并与分离
- 合并代码:如果多个模块共享信息或功能,通常应将它们合并为一个模块,以减少接口复杂性和信息泄漏。
- 分离代码:如果模块的功能过于复杂或职责不清晰,应考虑将其拆分为多个模块。
9. 消除错误
- 消除错误:通过重新定义 API 的语义,减少异常和错误处理的需求。例如,某些操作可以通过默认行为避免抛出异常。
- 异常屏蔽:在低层次模块中处理异常,避免将异常传播到高层次模块。
- 异常聚合:将多个异常处理逻辑合并为一个统一的处理机制,减少重复代码。
10.设计两次
- 设计两次:在设计模块或系统时,应考虑多个设计方案,并比较它们的优缺点。通过设计两次,开发者可以更好地理解问题,并选择最佳的设计方案。
11.注释的重要性
- 注释的作用:注释不仅仅是解释代码,它们还帮助隐藏复杂性,提供抽象。注释应描述代码中不明显的信息,而不是重复代码。
- 注释的层次:注释可以分为接口注释(描述模块的接口和行为)和实现注释(描述代码的内部实现)。接口注释应尽可能简洁,避免暴露实现细节。
实践指导
软件设计的核心目标是减少复杂性。通过遵循书中的设计原则,开发者可以创建更简单、更易维护的系统。复杂性是不可避免的,但通过良好的设计实践,可以有效地控制和管理复杂性。
- 避免浅模块:模块的接口应尽可能简单,隐藏复杂的实现细节。
- 信息隐藏:模块应隐藏其内部实现,减少依赖关系。
- 设计通用模块:模块的接口应设计得足够通用,能够适应多种使用场景。
- 将复杂性向下推:模块应尽可能处理内部的复杂性,而不是将复杂性暴露给使用者。
- 消除错误:通过重新定义 API 的语义,减少异常和错误处理的需求。
- 设计两次:在设计模块或系统时,应考虑多个设计方案,并比较它们的优缺点。
热门推荐
10年减10%!东京郊区新房越来越小,小户型公寓更受青睐
揭开中药煎煮的神秘面纱:别再迷信“越浓效果越好”!
如何查看护照的有效期?这种查看方式有什么注意点?
复旦大学团队开发胸膜间皮瘤基因治疗新策略
大圆套小圆问题(附解决源码)
Intel核心显卡驱动:如何安装、更新及解决常见问题?
杏核仁 【别名】杏仁
土地资源管理:实现可持续发展与环境保护的平衡
局域网实现HTTPS访问,OpenSSL生成自签名SSL证书
属鼠人的三种幸运色:金色、蓝色与粉色的寓意与搭配建议
谈谈优雅的钩子--bpftrace
谈谈优雅的钩子--bpftrace
病毒性脑炎需要做什么检查能查出来
「孕期听音乐」孕妇适合听什么音乐?
酒精中毒的表现与症状
93岁的巴菲特3点长寿之道:其中坚持跑步是他对健康最好的投资!
如何在规划房产投资收益时做出科学预测?这种预测如何提高收益准确性?
鲸、鲨的深潜之道
私募存在哪些风险及如何防范?私募投资的策略有哪些缺陷?
酒店设计指南:提升空间利用率与客人舒适度的空间布局策略
千年执壶与汤瓶
关于地震的谣言如何识破?5招教你甄别AI图片、视频
3·15“谣言解析”系列之一:向AI技术滥用乱象“亮剑”,筑牢网络安全防线
什么是数据统计中的标准差?
全国房价比峰顶降23%,70城回到1年前,专家:历史底部要抓住机会
英雄联盟如何投降
制定玉米期货交易的套期保值策略
期货玉米品种多样性的原因和市场影响是什么?投资者如何选择适合的玉米品种?
想体重管理的你 办公室健身指南→
如何分析黄金市场的供需关系?这种供需关系对价格有何影响?