找回密码
 立即注册
首页 业界区 安全 读整理优先:小改进,大回报,整洁代码设计指南(上) ...

读整理优先:小改进,大回报,整洁代码设计指南(上)

蔓好 9 小时前

1. 整理优先

1.1. 耦合和内聚只是度量计算机代码复杂度的标准,这不是从执行程序的计算机的角度来看的,而是从试图理解代码的人类的角度来看的
1.2. 软件设计是一种人际关系实践
1.3. 良好的软件设计是提高软件开发效率的强大工具,但如果使用不当,它就会变成另一个压迫工具,拖累软件开发的效率
1.4. 整理的理念之一是它永远不应该成为一件大事

  • 1.4.1. 不需要打报告、跟踪、计划和安排时间
  • 1.4.2. 之所以优先进行整理,是因为你需要改动代码,但代码很混乱,改起来很困难
1.5. 功能是所有人都关心的问题,所以我们今天要尽可能少地进行设计,这样才能回到功能开发上来
1.6. 经验性软件设计的时机取决于具体的情况
1.7. 极客设计软件的方式并不安全,有些方式会不小心破坏系统的行为,有些方式会让软件维护者倍感压力

  • 1.7.1. 不安全的行为产生不安全的感受是合理的,能感受到不安全远比毫不知情、毫不在意地感到安全要好得多
1.8. 当你优先整理时,你会立即感受到整理的价值
1.9. 完美的结果就是产生蝴蝶效应
2. 整理

2.1. 一般的学习策略是从具体到抽象

  • 2.1.1. 熟悉重构的人会发现,重构和整理之间有很大的相似之处,重构是在不改变行为的前提下改变结构
  • 2.1.2. 整理是重构的子集,是一种“可爱的、毛茸茸”的小重构,没有人会讨厌它
2.2. 卫述句

  • 2.2.1. 在深入代码的细节之前,需要处理一些前提条件
  • 2.2.2. 不要过多使用卫述句
2.3. 无用代码

  • 2.3.1. 如果代码不会被执行,就删掉
  • 2.3.2. 如果它就在那里,只需再次调用就能让它发挥价值,但如果删掉它而又需要它了,就会因为删除它而后悔
  • 2.3.3. 有时,无用代码很容易识别
  • 2.3.4. 有时,如果大量使用了反射,它们识别起来就不那么容易了
  • 2.3.5. 版本控制

    • 2.3.5.1. 我们并没有删除任何东西,只是现在不需要再看到它了
    • 2.3.5.2. 如果我们有很多代码但现在用不上,并且希望在未来使用它们而又不改变它们,那么我们就可以把它们找回来
    • 2.3.5.3. 可以再写一次,而且写得更好

  • 2.3.6. “少量”度量的是认知,而不是代码行数
2.4. 对称归一

  • 2.4.1. 代码量是自然增长的

    • 2.4.1.1. 我们不可能一次性写完所有需要的代码,除非我们从不学习任何东西

  • 2.4.2. 在自然增长的过程中,同样的问题可能在不同的时间或由不同的人以不同的方式解决
  • 2.4.3. 当交互使用两种或两种以上的模式时,就会变得混乱

    • 2.4.3.1. 不同的代码表达的是相同的事情

  • 2.4.4. 选择一种方式,将其他变体转换成这种方式

    • 2.4.4.1. 每次整理一种不必要的变体形式

  • 2.4.5. 细节会掩盖共性

    • 2.4.5.1. 寻找相似但不完全相同的例程,将不同的部分和相同的部分分离

2.5. 新接口,旧实现

  • 2.5.1. 你需要调用一个例程,而接口使调用变得困难、复杂、混乱或麻烦
  • 2.5.2. 创建直通接口是软件设计的微观本质
  • 2.5.3. 逆向编程

    • 2.5.3.1. 从例程的最后一行开始,就好像已经得到了所需的所有中间结果

  • 2.5.4. 先测试后编码

    • 2.5.4.1. 从需要通过的测试开始

  • 2.5.5. 设计辅助函数

    • 2.5.5.1. 如果只有一个例程/对象/服务能做XXX,那么剩下的事情就好办了

2.6. 阅读顺序

  • 2.6.1. 要抑制住诱惑,不要同时整理其他的问题
  • 2.6.2. 读完了整个文件后发现,最后的内容可以帮助你理解文件的前面部分
  • 2.6.3. 元素的排列顺序不可能尽善尽美
2.7. 内聚顺序

  • 2.7.1. 重新排列代码顺序,让需要更改的元素相邻
  • 2.7.2. 内聚顺序不仅适用于一个文件内的例程:如果两个例程是耦合的,就让它们相邻
  • 2.7.3. 内聚顺序也适用于目录中的文件:如果两个文件是耦合的,就把它们放在同一个目录中
  • 2.7.4. 内聚顺序甚至还适用于不同的代码库:把耦合的代码放在同一个代码库中,然后再修改它们
  • 2.7.5. 如果知道怎么消除,那尽管消除
  • 2.7.6. 解耦成本+变更成本<耦合成本+变更成本
  • 2.7.7. 解耦可能很难(不知道怎么解耦)​
  • 2.7.8. 解耦可能会耗费大量的时间和金钱(你可以做到,但现在花不起这个时间)
  • 2.7.9. 解耦可能是一种人际关系问题(团队已经到达了它所能承受的极限)
  • 2.7.10. 整理可以增加内聚性,使行为变更变得容易

    • 2.7.10.1. 内聚性稍有提高,就能清除解耦的障碍
    • 2.7.10.2. 更好的内聚性能让你更好地应对耦合

2.8. 将声明和初始化放在一起

  • 2.8.1. 变量及其初始化总是会渐行渐远
  • 2.8.2. 变量的名称可以告诉我们它在计算中的作用
  • 2.8.3. 初始化则会强化名称的信息
  • 2.8.4. 如果代码将(可能包含类型的)声明和初始化分离开来,阅读就会变得困难
  • 2.8.5. 变量和设置变量的代码不能随意排列

    • 2.8.5.1. 必须尊重变量之间的数据依赖关系
    • 2.8.5.2. 如果使用a初始化b,就必须先初始化a
    • 2.8.5.3. 要记住必须保持数据依赖关系的顺序

  • 2.8.6. 小步前进
2.9. 解释型变量

  • 2.9.1. 要把整理代码的提交与修改行为的提交分开
2.10. 解释型常量

  • 2.10.1. 把那些一起变化或需要一起理解的常量放在一块儿,并拆分那些由于别的原因而放在一起的常量
2.11. 显式化参数

  • 2.11.1. 人们常常用map来传递一组参数,但这样很难阅读和理解需要哪些数据
  • 2.11.2. 使用显式化参数的情况是在代码深处使用环境变量

    • 2.11.2.1. 将参数显式化,然后将其放到函数调用链的最前面
    • 2.11.2.2. 将使代码更易于阅读、测试和分析

2.12. 语句分块

  • 2.12.1. 软件设计让更改成为可能,小的软件设计可以让更改更容易
  • 2.12.2. 软件设计也会让后续更多的软件设计更容易
2.13. 提取辅助函数

  • 2.13.1. 有重构意识的人会发现这种整理与“提取方法”(Extract Method)类似
  • 2.13.2. 如果没有自动重构工具,执行这种整理/重构可能会很麻烦
2.14. 积沙成堆

  • 2.14.1. 根据需要尽可能多地内联代码,直到积沙成堆
  • 2.14.2. 代码的最大成本不是编写成本,而是阅读和理解的成本
  • 2.14.3. 整理优先倾向于大量的小片段,理论上可以增加内聚性、降低耦合性,实际上也可以减少大量细节
  • 2.14.4. 目的是让人们一次理解少量代码
  • 2.14.5. 症状

    • 2.14.5.1. 冗长、重复的参数列表
    • 2.14.5.2. 重复的代码,尤其是重复的条件
    • 2.14.5.3. 辅助函数命名不当
    • 2.14.5.4. 共享可变数据结构

2.15. 解释型注释

  • 2.15.1. 如果你发现一个文件没有header,可以考虑添加一个header,告诉潜在的读者这个文件的价值
  • 2.15.2. 写注释的一个好时机是在发现缺陷的时候
  • 2.15.3. 添加注释指出耦合问题,要比把它埋在沙子里好得多
2.16. 删除多余注释

  • 2.16.1. 当看到与代码内容完全一致的注释时,就将其删除
  • 2.16.2. 代码的目的是向其他程序员解释你希望计算机做的事情
  • 2.16.3. 当系统发生变化时,没有任何机制可以检查注释的准确性,而且随着代码的演化,注释可能会变得多余

    • 2.16.3.1. 注释一开始并不是多余的
    • 2.16.3.2. 经过整理后,注释只是对代码内容的简单重复


来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册