美文网首页iOS,程序,设计,产品相关代码改变世界PMbook
读《编程匠艺—编写卓越的代码》:编写“自文档化”代码

读《编程匠艺—编写卓越的代码》:编写“自文档化”代码

作者: 思学 | 来源:发表于2015-01-06 20:54 被阅读346次

    欧内斯特.海明威(Erners Hemingway) :
    严肃是写作必备的两大要素之一。另一个,很不辛,是天分

    我们编写代码,是要表达一套清晰的指令,它不仅仅面向电脑,也面向修改、拓展和维护这些指令的人。

    在软件产品的生命周期内,代码将不断地被修改、拓展和维护。所以文档化代码是一件有益的工作。

    一、如何代码文档化

    1. 编写大量关于代码的文档
      有时可以见到由设计规范、实现说明、维护指南和风格指南支持的软件系统,这种做法会导致如下问题:
      (a).除了编写程序外,要耗费大量时间去编写文档和阅读文档;
      (b).所有文档必须随代码更改而及时更新,否则会导致危险的错误和产生误导信息;
      (c).大量文档的管理也是一大问题;
      (d).由于信息没有放在代码旁,一些重要信息容易被忽略。

    2. 使用详细的代码注释
      这是一种可选方案,但容易写出一堆毫无创造性的逐条注释。

    3. 最理想的方案:写自文档化的代码
      我们要相信:唯一能完整并正确地描述代码的文档是代码本身
      我们应当尽可能地编写可读性高的代码,这种代码本身易于理解,甚至不需要任何外部文档或注释加以说明。如下面这段代码:

    int fibonacci(int position)
    {
          if (position < 2)
          {
              return 1;
          }
          int previousButOne = 1;
          int previous       = 1;
          int answer         = 2;
    
          for (int i = 2; i < position; i++)
          {
                    previousButOne = previous;
                    previous       = answer;
                    answer         = previousButOne + previous;
           } 
           return answer;
    }
    

    这段代码没有注释,但我们很容易读懂它。

    二、编写"自文档化"代码的技能:

    1. 使用好的样式,编写简单的代码
      (a).程序流程分明。错误情况不会扰乱程序正常执行流程;
      (b).避免使用过多的嵌套语句;
      (c).谨慎地优化代码,让它清晰地表达基础算法。
    2. 选择有意义的名称
      具体见《读《编程匠艺—编写卓越的代码》:命名》
    3. 用多个简单的函数代替复杂的函数
      (a).一个函数,一种操作;
      (b).减少任何出人意料的副作用,它们会要求额外文档的;
      (c).保持简短,短小的函数更易于理解。
    4. 选择描述性的类型
      (a).定义永远不变的值为常值变量(C/C++使用const);
      (b).定义非负变量为无符号类型;
      (c).使用枚举描述一组相关值;
      (d).选择适当类型。C/C++中,将值的大小放入size_t变量,将指针放入ptrdiff_t变量。
    5. 命名常量
      对于常量字符串和数字,不要直接在代码中使用。如if (counter == 72)这样的代码会让人无法理解,神奇数字72是什么,if的目的是什么呢,我们不知道;但如果写成
    const size_t bananas_per_cake = 72;
    ....
    if (count == bananas_per_cake)
    {
          //做香蕉蛋糕
    }
    

    就清晰很多。容易明白数字72代表每个蛋糕需要的香蕉数目,而且如果需要改变数字72,只需做一个改动即可。

    1. 强调重要的代码
      (a).在类中按一定数序进行声明:用户需要的公共信息在前,对用户不重要的私有的实现细节放在后面;
      (b).尽可能隐藏所有不重要信息。C++中,使用pimpl idiom实现类的实现细节;
    2. 尽可能通过语言结构将对象分组
      C++/C#中通过命名空间分组;Java中使用包分组。
    3. 提供文件头
      在文件顶部放置一个注释块,简述文件内容、所属项目及版权声明*
    4. 恰当地处理错误
      (a). 在最恰当的上下文中处理错误;
      (b).不要返回无意义的错误信息。
    5. 编写有意义的注释
      先考虑优化代码(如换一个名字或新增一个下属函数)。只有在你无法以任何其他方式来提高代码清晰度的情况下,再添加恰当的注释。

    三、实用的自文档化方法

    《编程风格的元素》中Kernighan和Plaugher:
    不要对糟糕的代码进行文档化——重写这些代码。

    A. 文学编程

    著名计算机科学家Donald Knuth在他的1992年出版的《文学编程》提出了一种极端的自文档化代码技巧——文学编程,并在书中详细描述了这种编程方法。

    B.文档化工具

    利用工具通过分离特殊格式的注释块,从源代码生成文档。

    可以文档化你编写的任何代码:类、类型、函数、参数、标志、变量等,还能方便地获取大量信息:

    • 指定版本信息
    • 记录创建日期
    • 交叉引用信息
    • 将旧代码标记为过时
    • 为快速引用提供简短的对照表
    • 描述每个函数的参数

    流行的代码文档化工具有:

    • Java的Javadoc
    • C#的NDoc
    • 适用于多种编程语言的Doxygen

    一些有用的经验:

    • 对于每个公共可见的对象,都编写一两句描述,不要冒险写太多文字。
    • 如果变量或参数用途不明显,请简要说明;如果它们的名字表达的很清楚,则不用添加描述
    • 如果函数的一些参数用于输入,另一些用于输出,需明确说明
    • 不要文档化任何一个函数的前置和后置条件

    四、总结

    埃德温·施罗斯伯格(Edwin Schlossberg):
    写作的技巧就是创建一个上下文语境,别人在其中思考

    代码本身就是一种交流媒介,考虑那些需要维护代码的程序员们的需求,努力写出清晰的代码——用最少最恰当的注释/文档,用"自文档化"的代码。

    内容相关

    Pimpl idiom
    Pimopl是C++开发中经常使用的一种惯用法,其原理主要是将对定义的依赖转换为对声明的依赖,通过前向声明,达到接口与实现的分离的效果,并将编译时文件间的依赖降到最低,从而大大缩短程序编译的时间。简单点说,就是将一个类分割为两个类,一个提供接口,一个负责实现,既能最小化编译依赖,又能接口与实现分离。Pimpl的实现方式有两种,第一种是让实现类成为接口类的一个私有指针成员变量;另一种实现方式则是通过继承的方式实现:让接口类成为抽象基类,这个基类包含一个返回该类指针的静态方法,该方法通过实现类的构造函数实现,实现类继承自这个抽象基类,并实现基类描述的接口。『示例可查看PIMPL IDIOM & FAST PIMPL

    写作与编程
    关于写作技巧的提高,有一个简单的原则:读的书越多,写得就越好。用批判的眼光阅读著名作者的作品,可以使你学会如何分辨好坏,还能从中学到新的技巧和习惯用法。类似的,如果你阅读大量优秀的代码,那么你也会成为一位更出色的程序员。你会在编写代码时不自觉地运用好的技巧,一旦写出糟糕的代码,你会立马警觉,甚至浑身不自在。

    相关文章

      网友评论

        本文标题:读《编程匠艺—编写卓越的代码》:编写“自文档化”代码

        本文链接:https://www.haomeiwen.com/subject/famtxttx.html