12.1 好的代码是自文档化的
Last updated
Last updated
有些人认为,如果代码写得好,就会很易于理解,不需要注释。这是一个美味的神话,就像冰激凌对健康有益的传言一样:我们真的愿意相信它!不幸的是,这根本不是真的。可以肯定的是,在编写代码时,你可以做一些事情来减少对注释的需求,比如选择好的变量名称(见第14章)。尽管如此,仍然有大量的设计信息不能用代码来表示。例如,只有一个类的接口的一小部分,如其方法的签名,可以在代码中规范指定。接口的非规范方面,比如对每个方法的作用或其结果的意义的高级描述,只能写在注释中。还有很多其他不能在代码中描述的例子,比如某个特定设计决策的理由,或者在什么条件下调用某个特定方法是有意义的。
一些开发者认为,如果其他人想知道某个方法是做什么的,他们应该直接阅读该方法的代码:这将比任何注释都要准确。读者有可能通过阅读方法的代码来推断出方法的抽象接口,但这将是非常耗时和痛苦的。此外,如果你在写代码时期望用户会阅读方法的实现,那么你将尽量使每个方法简短,以便于阅读。如果该方法做了什么重要的事情,你会把它分成几个小方法。这将导致大量浅方法的出现。此外,这并不能真正使代码更容易阅读:为了理解顶层方法的行为,读者可能需要理解嵌套方法的行为。对于大型系统来说,让用户通过阅读代码来了解行为并不实际。
此外,注释是抽象的基础。回顾,抽象的目标是隐藏复杂性:抽象是一个实体的简化视图,它保留了基本信息,但省略了可以安全地忽略的细节。如果用户必须阅读一个方法的代码才能使用它,那么就没有抽象了:这个方法的所有复杂性都暴露无遗。如果没有注释,一个方法的唯一抽象就是它的声明,它规定了它的名字以及参数和结果的名称和类型。声明中缺失了太多必不可少的信息,所以它本身无法提供一个有用的抽象。例如,一个提取子串的方法可能有两个参数,start
和end
,表示要提取的字符范围。仅仅从声明中,我们不可能知道提取的子串是否包括end
所指示的字符,或者如果start > end
会发生什么。注释允许我们捕获调用者需要的额外信息,从而完成简化的视图,同时隐藏实现细节。同样重要的是,注释要用人类的语言来写,比如英语;这使得它们没有代码那么精确,但它提供了更多的表达能力,所以我们可以创建简单、直观的描述。如果你想使用抽象来隐藏复杂性,注释是必不可少的。