如何高效编写可维护代码?

原文:How to make your code self-documenting?

译文:怎么让代码自我文档化?

译者:dwqs

在代码中找到一个放错地方并且没有用的注释是不是很有趣呢?

怎么样才能做到写很少的注释但仍能让代码易于理解呢?

一个主要的方式就是让代码自我文档化。当代码自我文档化的时候,就不需要注释去它的作用或者目的,并且也能使代码变得非常容易维护。

在这篇文章中,我将提供一些让你的代码自我文档化的方式。下面就是三种使得代码自文档化的基本方法:

  • 命名:利用名字来解释变量、函数等的目的。
  • 封装函数:将一些特定功能的代码封装成一个函数以明确目的。
  • 引入变量:将表达式插入至专用变量。

这可能看上去很简单,但在实际操作过程中会让人觉得有点棘手。首先你得明白哪些地方有问题以及哪些地方适用这些方法。

此外,除了上述三种,还有一些应用比较广泛的方式:

  • 类和模块接口:将类和模块中的函数暴露出来,让代码更加清晰。
  • 代码分组:用组来区分不同的代码片段。

接下来我们将通过实例,具体讲一讲如何在实际应用中运用上述5个方法。

一、命名

首先,看几个如何利用命名时代码变得清晰和自我文档化的例子。

1、重命名函数

给函数命名不是很难,你可以遵守以下规则:

  • 避免使用含糊的字眼,例如“handle”或“manage”——handleLinks、manageObjects。
  • 使用主动动词——cutGrass、sendFile,以表示函数主动执行。
  • 指定返回值类型——getMagicBullet、READFILE。强类型的语言也可以用类型标识符来表明函数的返回值类型。

  2、重命名变量

  • 指定单位——如果里面有数值参数,那可以加上其单位。例如,用widthPx来取代width以指定宽度的单位是像素。
  • 不要使用快捷键——a和b都不能作为参数名。

二、函数封装

接下来,看几个如何将代码封装成函数的例子。封装函数的一个好处就是避免代码重复,或者说改进代码结构。

1、将代码封装成函数

这是最基本的:将代码封装成函数以明确其目的。猜猜下面这行代码是干什么的:

  好像不是很清楚,当然有注释就一清二楚了,但是我们完全可以封装成函数以实现自文档化……
var width = emToPixels(value);

function emToPixels(ems) {
    return (ems - 0.5) * 16;
}

唯一改变的是计算过程被转移到了一个函数里。该函数名明确地表达了它要做什么,这样一来就不必写注释了。而且,如果有需要后面还可以直接调用此函数,一举两得,减少了重复劳动。

  2、用函数代替条件表达式

If语句如果包含多个运算对象,不写注释的话理解起来就比较难。

function isVisible(el) {
    return el.offsetWidth && el.offsetHeight;
}

if(!isVisible(el)) {
}

三、引入变量

最后再讲讲如何引入变量。相较于上面两个方法,这个可能没那么有用,但是无论如何,知道比不知道好。

  1、用变量代替表达式

看看上面的例子

var isVisible = el.offsetWidth && el.offsetHeight;
if(!isVisible) {
}

  2、用变量代替方程式

我们也可以用来清楚说明复杂程式:

  用变量来代替
var divisor = c / d;
var multiplier = a * b;
return multiplier + divisor;

四、类和模块接口

类和模块的接口——也是面向公共的方法和属性——有点像说明如何使用的文档。

看下面的例子:

class Box {
    public function setState(state) {
        this.state = state;
    }

    public function getState() {
        return this.state;
    }
}

这个类也可以包含其他代码。我特意举这个例子是想说明公共接口如何自文档化。

你能说出这个类是如何被调用的吗?很显然,这并不明显。

这两个函数都应该换个合理的名字以表述它们的目的。但即便做到这一点,我们还是不怎么清楚如何使用。然后就需要阅读更多的代码或者翻阅文档。

但是如果我们这样改一下呢……

class Box {
    public function open() {
        this.state = open;
    }

    public function close() {
        this.state = closed;
    }

    public function isOpen() {
        return this.state == open;
    }
}

是不是清晰多了?注意:我们只是改动了公共接口,其内部表达与原先的this.state状态相同。

五、代码分组

用组来区分不同的代码片段也是自文档化的一种形式。例如,像这篇文章中说的那样,我们应该尽可能将变量定义在靠近使用它的地方,并且尽可能将变量分门别类。这也可以用来指定不同代码组之间的关系,这样更加方便其他人知道他们还需要了解哪些代码组。

看下面的例子:

var foo = 1;

blah()
xyz();

bar(foo);
baz(1337);
quux(foo);

与下面的比较:

var foo = 1;
bar(foo);
quux(foo);

blah()
xyz();

baz(1337);

将foo的所有使用组合放在一起,一眼望去就能知道各种关系。但是有时候我们不得不在中间调用一些其他函数。所以如果可以那就尽量使用代码分组,如果不可以,那就不要强求。

六、其它建议

  • 不要使用奇怪的标记,下面两个是等价的
if(imTricky) {
    doMagic();
}

显然后者比较好。语法技巧并没有带来什么好处。

  • 命名常量:如果代码里面有一些特殊值,那最好给它们命名。var PURPOSE_OF_LIFE = 42;
  • 制定规则:最好遵循相同的命名规则。这样阅读的人就能在参考其他代码的基础上正确猜测出各种事物的含义。

原文首发:http://www.ido321.com/1360.html

时间: 2024-12-13 05:01:08

如何高效编写可维护代码?的相关文章

如何编写无法维护的代码 让自己稳拿铁饭碗 ;-)

如何编写无法维护的代码 让自己稳拿铁饭碗 ;-) Roedy Green 简介 永远不要(把自己遇到的问题)归因于(他人的)恶意,这恰恰说明了(你自己的)无能.-- 拿破仑 为了造福大众,在Java编程领域创造就业机会,兄弟我在此传授大师们的秘籍.这些大师写的代码极其难以维护,后继者就是想对它做最简单的修改都需要花上数年时间.而且,如果你能对照秘籍潜心修炼,你甚至可以给自己弄个铁饭碗,因为除了你之外,没人能维护你写的代码.再而且,如果你能练就秘籍中的 全部 招式,那么连你自己都无法维护你的代码了

如何编写无法维护的代码

如何编写无法维护的代码 让自己稳拿铁饭碗 ;-) Roedy Green 简介 永远不要(把自己遇到的问题)归因于(他人的)恶意,这恰恰说明了(你自己的)无能.-- 拿破仑 为了造福大众,在Java编程领域创造就业机会,兄弟我在此传授大师们的秘籍.这些大师写的代码极其难以维护,后继者就是想对它做最简单的修改都需要花上数年时间.而且,如果你能对照秘籍潜心修炼,你甚至可以给自己弄个铁饭碗,因为除了你之外,没人能维护你写的代码.再而且,如果你能练就秘籍中的 全部 招式,那么连你自己都无法维护你的代码了

如何编写可维护的面向对象JavaScript代码

能够写出可维护的面向对象JavaScript代 码不仅可以节约金钱,还能让你很受欢迎.不信?有可能你自己或者其他什么人有一天会回来重用你的代码.如果能尽量让这个经历不那么痛苦,就可以节省不少时 间.地球人都知道,时间就是金钱.同样的,你也会因为帮某人省去了头疼的过程而获得他的偏爱.但是,在开始探索如何编写可维护的面向对象JavaScript代码之前,我们先来快速看看什么是面向对象.如果已经了解面向对象的概念了,就可以直接跳过下一节. 什么是面向对象?  面向对象编程主要通过代码代表现实世界中的实

如何使用 require.js ,实现js文件的异步加载,避免网页失去响应,管理模块之间的依赖性,便于代码的编写和维护。

一.为什么要用require.js? 最早的时候,所有Javascript代码都写在一个文件里面,只要加载这一个文件就够了.后来,代码越来越多,一个文件不够了,必须分成多个文件,依次加载.下面的网页代码,相信很多人都见过. 1 <script src="1.js"></script> 2 <script src="2.js"></script> 3 <script src="3.js">

一步步教你编写不可维护的 PHP 代码

译者注:这是一篇很棒文章,使用有趣的叙述方式,从反面讲解了作为一个优秀的 PHP 工程师,有哪些事情是你不能做的.请注意哦,此篇文章罗列的行为,都是你要尽量避免的. 随着失业率越来越高,很多人意识到保全自己的工作是多么的重要.那么,什么是保住自己工作,并让自己无可替代的好方法呢?一个很简单的事实是只要你的代码没有人能够维护,那么你就成功保住了工作.编写不可维护的代码是一个特殊的技能,但奇怪的是,似乎对某些开发者来说是很自然的.不过对于剩下的开发者来说,这里有一些技巧和提示来让你开始写不可维护的代

代码质量优先——《编写高质量代码:改善c程序代码的125个建议》

高质量的代码不但可以促进团队合作.减少bug处理.降低维护成本,对程序员自身的成长也是至关重要的.很难想象一个参考<如何编写无法维护的代码>写代码的程序员技术成长的上限有多么低.为了写出高质量的代码,我们需要听取过来人的改善代码质量的经验,<编写高质量代码:改善c程序代码的125个建议>就是一本能让人写出高质量代码的好书. 本书的第三章<程序控制语句应该保持简洁高效>首先用简练的语言介绍了流程控制结构的概念,然后提供了对if.else.for.do-while.swit

编写高质量代码,改善C++程序的150个建议:指针、初始化和运算符

建议0:不要让main函数返回void 首先C++ 标准中从没有出现过void main(){}这样的函数定义. 标准的主函数定义有两种: int main() int main(int argc,char * argv[]) 在main函数中,return 语句的作用在于离开main函数(析构掉所有具有动态生存时间的对象),并将其返回值作为参数来调用exit函数.如果函数执行到结尾儿没有遇到return 语句,其效果就等于执行了return 0. 建议1:区分0 的四种面孔 1)整形0.作为一

Python 工匠:编写条件分支代码的技巧

序言 编写条件分支代码是编码过程中不可或缺的一部分. 如果用道路来做比喻,现实世界中的代码从来都不是一条笔直的高速公路,而更像是由无数个岔路口组成的某个市区地图.我们编码者就像是驾驶员,需要告诉我们的程序,下个路口需要往左还是往右. 编写优秀的条件分支代码非常重要,因为糟糕.复杂的分支处理非常容易让人困惑,从而降低代码质量.所以,这篇文章将会种重点谈谈在 Python 中编写分支代码应该注意的地方. Python 里的分支代码 Python 支持最为常见的 if/else 条件分支语句,不过它缺

Python :编写条件分支代码的技巧

『Python 工匠』是什么? 我一直觉得编程某种意义是一门『手艺』,因为优雅而高效的代码,就如同完美的手工艺品一样让人赏心悦目. 在雕琢代码的过程中,有大工程:比如应该用什么架构.哪种设计模式.也有更多的小细节,比如何时使用异常(Exceptions).或怎么给变量起名.那些真正优秀的代码,正是由无数优秀的细节造就的. 序言 编写条件分支代码是编码过程中不可或缺的一部分. 如果用道路来做比喻,现实世界中的代码从来都不是一条笔直的高速公路,而更像是由无数个岔路口组成的某个市区地图.我们编码者就像