豆瓣读书:https://book.douban.com/subject/1477390/
《Code Complete》2d ed,CC2
目录
第 1 章 欢迎进入软件构建的世界
软件开发过程中的主要活动(activity):
- 定义问题(problem definition)
- 需求分析(requirements development)
- 规划构建(construction planning)
- 软件架构(software architecture)
- 详细设计(detailed design)
- 编码与调试(coding and debugging)
- 单元测试(unit testing)
- 集成测试(integration testing)
- 集成(integration)
- 系统测试(system testing)
- 保障维护(correcting maintenance)
在开始学习本书的其他内容之前,回顾这些软件工程的内容,可以有一个非常好的、非常有用的背景知识,学习基调。更有大局观,知道自己从这本《大码大全》学到的东西是处于什么样的位置里。
构建活动的具体任务(task)
- 验证有关的基础工作已经完成,因此构建活动可以顺利地进行下去。
- 确定如何测试所写的代码。
- 设计并编写类(class)和子程序(routine)。
- 创建并命名变量(variable)和具名常量(named constant)。
- 选择控制结构(control structure),组织语句块。
- 对你的代码进行单元测试和集成测试,并排除其中的错误。
- 评审开发团队其他成员的底层设计和代码,并让他们评审你的工作。
- 润饰代码,仔细进行代码的格式化和注释。
- 将单独开发的多个软件组件集成为一体。
- 调整代码(tuning code),让它更快、更省资源。
在上述的“软件工程”知识的基础之上,对本书的关键内容的整体流程也先来个感性认识。
一些重要的非构建活动
- 管理(management)
- 需求分析
- 软件架构设计
- 用户界面设计
- 系统测试
- 维护
也不要忽略本书不详细讲解的其他软件开发过程中重要内容。
软件构建为何如此重要
- 构建活动是软件开发的主要组成部分。
- 构建活动是软件开发中的核心活动。
- 把主要精力集中于构建活动,可以大大提高程序员的生产率。
- 构建活动的产物 —— 源代码 —— 往往是对软件的唯一精确描述。
- 构建活动是唯一一项确保会完成的工作。
第 2 章 用隐喻来更充分地理解软件开发
先来体验一下计算机科学领域中丰富多彩的语言,大量使用了形象的隐喻:
你走进一间安全严密、温度精确控制在 20℃ 的房间,并在里面发现了病毒、特洛伊木马、蠕虫、臭虫(bug)、逻辑炸弹、崩溃、论坛口水战、双绞线转换头、还有致命错误……
很正的科学观:
科学发展的历史并不是一系列从“错误”的隐喻到“正确”的隐喻的转变,而是一系列从“不太合适”的隐喻到“更好”的隐喻的转变,也是从不是很贴切的隐喻到更贴切的隐喻的转变,还是从一个方面暗示人们到另一个方面暗示人们的转变。
注意隐喻的使用,并不是用来说明算法步骤:
隐喻的作用更像启示(heuristic,启发、试探法),而不是算法(Algorithm)。
常见的软件隐喻:
- “写作”代码。就像写文章一样把代码写出来。使用这样的隐喻来理解个人的小项目软件开发是合适的。但还是过于简单了,无论是像流水账一样写下去直到写完还是总写到一半就把草稿扔废纸篓,都不是明智的。
- 培植系统。种下各种类型的种子,等到了秋天就收获丰盛的代码了。问题在于,暗示了人们无法对软件开发的过程和方式进行直接的干预,只能看天吃饭。
- 系统生长。在培植系统的基础上,我们关注代码种子的发芽、生长,要时刻施肥、打理。这有点把大系统分解为多个小部分并逐步添加代码的意思了。也就是增量式开发。如今敏捷开发里吗很重要的思想也包含这层意思。
- 建造软件。这个隐喻是从建筑行业借用过来的。包括著名的四人帮《设计模式》,pattern 这个词,也是从建筑中借用。还有,前两年《人月神话》的作者出了一本《设计原本》(The Design of Design),好厉害的名字。其里面也是大量篇幅讲到了建筑设计。基于发展很完备的建筑行业来隐喻,这次,可以把软件开发问题说得很清楚了。软件开发确实很复杂,还要慢慢领会。
第 3 章 三思而后行:前期准备
3.1 前期准备的重要性
- 降低风险
- 避免“解决了一个错误的问题”
- 避免采用的开发方法不符合软件特点
- 程序员是软件食物链的最后一环。产品经理挖出需求,架构师吃掉需求,设计师吃掉架构,而程序员则消化设计。
3.2 辨明你所从事的软件的类型
- 三种典型的软件项目类别
- 商业系统
- 使命有关的系统
- 性命攸关的嵌入式系统
- 适合序列式开发方法的特点
- 需求相当稳定
- 设计直截了当,而且理解透彻
- 开发团队对于这一应用领域非常熟悉
- 项目的风险很小
- “长期可预测性”很重要
- 后期改变需求,设计和编码的代价可能比较昂贵
- 适合迭代式开发方法的特点
- 需求并没有被理解透彻,或是不稳定
- 设计很复杂、有挑战性
- 开发团队不熟悉这一应用领域
- 项目包含许多风险
- “长期可预测性”不重要
- 后期改变需求、设计和编码的代价较低
3.3 问题定义的先决条件
- 问题定义应该用客户的语言来书写,而且应该从客户的角度来描述问题,不应该使用计算机专业术语。
- 如果没有明确的问题定义,那么你可能会在构建期间解决错误的问题。
3.4 需求的先决条件
- 明确需求,无需再猜测用户想要什么。
- 需求变更在很多情况下无法完全避免,因为开发过程帮助客户更深入地了理解了自己的需求。
- 应对需求变更的方法
- 确保每一个人都知道需求变更的代价
- 建立一套变更控制流程
- 采用能适应变更的开发方法
- 放弃这个项目
- 对照需求核对表进行检查,确保需求已做好。
3.5 架构的先决条件
- 架构的典型组成部分
- 程序组织,系统结构
- 主要的类
- 数据设计
- 业务规则
- 用户界面设计
- 资源管理
- 安全性
- 性能
- 可伸缩性
- 互用性(与其他系统交互)
- 国际化、本地化
- 输入输出
- 错误处理
- 容错性
- 架构的可行性
- 过度工程(多做比必要的工作)
- 关于“买”还是“造”的决策
- 关于复用的决策
- 变更策略
- 架构的总体质量
- 对照架构核对表进行检查,确保架构已做好。
3.6 花费在前期准备上的时间长度
- 一般来说,一个运作良好的项目会在需求、架构以及其他前期计划方面投入 10% - 20% 的工作量和 20% - 30% 的时间。
对照前期准备核对表进行检查,确保前期准备工作已做好:
第 4 章 关键的“构建”决策
第 3 章关注焦点是确定“当构建开始后你需要做什么”,本章关注的焦点是程序员和技术带头人必须负责的准备工作,是更加具体、细致的内容。
4.1 选择编程语言
- 编程语言的影响
- 开发人员使用熟悉的语言时,比使用新语言的生产率高 30%。
- 使用高级语言比低级语言能达到更好的生产率和质量。
- 使用合适的语言能更好的设计、表达出编程思想。你的思考能力取决于你是否知道能够表达该思想的语言,否则你无法表达,甚至无法形成这种思想。
- 选择合适的语言,清楚了解其优点和缺点,“深入一种语言去编程”,不要仅“在一种语言上编程”。当语言不完善或不满足某种用法是,可以尝试设计出新的“约定”来达到更好的开发效果。
4.2 编程约定
- 架构设计与具体编码实现须保持一致。
- 具体到变量、类、函数的命名,代码格式,注释撰写等的风格一致性。
- 预先设计约定,统一规则,避免创作出来的东西充斥各种不同风格,线的混乱而邋遢。造成理解和维护的沉重负担。
4.3 你在技术浪潮中的位置
- 处于技术浪潮中不同的位置需要采用不同的编程实践。
- 如果处于浪潮后期,可以计划用大部分时间稳定持续地编写新功能。
- 如果处于浪潮前期,可以预期你将花大量时间处理未完善的开发语言、程序库等基础设施的问题。所以主要注意相应调整开发计划和预期目标。
4.4 选择主要的构建实践方法
2020年11月12日