`

注释源代码表明你写的代码还不好

阅读更多
原文地址:
http://www.urubatan.info/2008/11/commenting-source-code-is-only-for-the-weak/

你们中的许多人可能不同意我的看法,但是当你阅读完了本篇文章,你将可能同意这点:
注释你自己的源代码是你写的代码不好看的标志。真正的程序员是写他人能读的代码!

但是记住我谈论的是说明代码是干什么的那样的注释,而不是诸如Javadoc那样的文档。

举一个例子:如果你不了解抑或不是一个Java程序员,你能很快地说出以下的代码是干什么的吗?


public String write(StringBuilder fle, StringBuffer con) {
  File f = new File(fle.toString());
  FileReader fr = new FileReader(f);
  BufferedReader br = new BufferedReader(fr);
  String lin;
  while((lin=br.readLine())!=null){
    con.append(lin).append("\n");
  }
  return con.toString();
}


困难吗?这只是一段非常简单的代码,但是我们可以让它变得再好一点...

public String read(StringBuilder fle, StringBuffer con) {
  //Opens the file with the name container in the fle parameter
  File f = new File(fle.toString());
  //Create a file reader, then a buffered reader to make our work easier
  FileReader fr = new FileReader(f);
  BufferedReader br = new BufferedReader(fr);
  String lin;
  //Read each line of the file until it is null
  while((lin=br.readLine())!=null){
    //Put the content read into the buffer pointed by the parameter "con"
    con.append(lin).append("\n");
  }
  //The caller already have the content, because he created the buffer, but I'll return the string anyway
  return con.toString();
}


简单一些了吧,对吗?现在你读着代码中的注释,并且也理解了它,但是代码仍然是不好看。

这种类型的注释就是我在现在谈论的。注释你的源代码表明你是一个非常糟糕的程序员(一个小例外就是遇到不能将代码分解成小片断的很复杂的算法)。

当你在注释你的代码,你实际上是在用一种HACK的方式向他人掩饰你所做的不合格。这表明了你不会写干净的代码。不会写让其他程序员可读的代码!

现在我就就上面写的代码,来重构一下其中的难读的方法。


public String readFileContents(File fileToRead) {
  boolean canReadFile = fileToRead.exists();
  if(!canReadFile)
    return "";
  StringBuilder buffer = new StringBuilder();
  BufferedReader readerForFile = openBufferedReaderForFile(fileToRead);
  readFileContetIntoBuffer(buffer,readerForFile);
  closeFileReader(readerForFile);
  return buffer.toString();
}
private  BufferedReader openBufferedReaderForFile(File fileToRead){
  return new BufferedReader(new FileReader(fileToRead));
}
private void readFileContetIntoBuffer(buffer,readerForFile){
  String line;
  while((line=readerForFile.readLine())!=null){
    buffer.append(line).append("\n");
  }
}
private void closeFileReader(readerForFile){
  readerForFile.close();
}

现在,你注意一下名为readFileContents的方法,你已经知道了它是干什么的,另外,方法的代码很容易理解的,如下面意思所表明的意思:

引用

如果不能读文件,返回null,
为名为fileToRead的File打开Buffered Reader,
将文件的内容读到缓存中去,关闭File Reader readerForFile,
返回buffer.toString();


我所表达的说明了:如果你懂英语,你就能读懂代码,而几乎每个程序员都知道英语,对吗?(我注:当然非英语国家...)

我曾看到有人写了如下的很糟糕的代码,如同下面这个样子:

public String write(StringBuilder fle, StringBuffer con) {
  File f = new File(fle.toString()); FileReader fr = new FileReader(f);  BufferedReader br = new BufferedReader(fr);
String lin; while((lin=br.readLine())!=null){  con.append(lin).append("\n");  }
  return con.toString();
}


这个比我的版本的行数少,但是你要上一段困难的时间试图弄懂这个糟糕的程序员写出的如上的代码片断。

当然,我使用的这个例子非常简单,并且我知道写出清析易读的代码是需要实践的...

但是我给你一个提议,不是一个真正的提议,是一个练习而已...

我写了一个如下的代码示例,你试着将它变成可读的。我会在一两天后贴出我的解决方案。

你们可以直接在文章回复中贴出你们的重构代码。


package blog;
 
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
 
public class VeryBadlyNamedFile {
	private static final char[] asdfg = new char[] {'I', ' ', 'c', 'a', 'n', ' ', 'd', 'o', ' ', 'v', 'e', 'r', 'y', ' ', 'u', 'g', 'l', 'y', ' ', 'c', 'o', 'd', 'e'};
	private String an;
	private BufferedReader rfsdw;
	private FileReader temp;
 
	public VeryBadlyNamedFile(String an, BufferedReader rfsdw, FileReader temp) {
		super();
		this.an = an;
		this.rfsdw = rfsdw;
		this.temp = temp;
	}
 
	public void doIt() throws IOException {
		ctfiidne();
		startDoing();
		try {
			canIDoAnyThing();
		} catch (RuntimeException yicdet) {
			nowReallyDoIt();
		}
	}
 
	private void nowReallyDoIt() {
		firstDoTheOtherThing();
		reallyDoItInternal();
	}
 
	private void firstDoTheOtherThing() {
		rfsdw = new BufferedReader(temp);
	}
 
	private void reallyDoItInternal() {
		while (true) {
			try {
				imDoingIt();
			} catch (Exception e) {
				break;
			}
		}
	}
 
	private void imDoingIt() throws Exception {
		String s = rfsdw.readLine();
		if (s == null)
			throw new Exception("hahaha, I bet you did not understood the code");
		System.out.println(s);
	}
 
	private void ctfiidne() throws IOException {
		File a = new File(an);
		if (!a.exists()) {
			FileWriter wrfedsd = new FileWriter(a);
			wrfedsd.write(asdfg);
			wrfedsd.close();
		}
	}
 
	private void canIDoAnyThing() {
		if (new File(an).exists() && new File(an).canRead() && new File(an).canWrite())
			throw new RuntimeException();
	}
 
	private void startDoing() throws FileNotFoundException {
		File f = new File(an);
		temp = new FileReader(f);
	}
}


现在用一个主程序执行上面的代码:

package blog;
 
import java.io.IOException;
 
public class Main {
	public static void main(String[] args) throws IOException {
		new VeryBadlyNamedFile("c:\\anyFile.any",null,null).doIt();
	}
}


以上的这些例子用的是Java代码,但是本观点适用于任意语言,如果你编程,并且用注释来解释你的代码,那么你是一个可怕的程序员。


快点祈祷上帝的帮助,乞求下一个读了你废话般的代码的的人不是一个知道你住处的连环杀手!

PS.:我真的不认为你不应该注释你的代码,但是 如果你的代码如果没有注释就理解不了,那表明你还不会写程序。

PS2.: 我觉得我应该来些更好的例子。

PS3.: 写出好代码的秘诀就是你写代码即使你知道下一个阅读你代码的人是一个连环杀手,并且知道你住在哪儿。(个人理解就是我们时刻要记住写出的代码是要给人家看的)


------我的分割线------
在现实生活中,我常常遇到还没有达到如作者说的那样
public String write(StringBuilder fle, StringBuffer con) {
  File f = new File(fle.toString()); FileReader fr = new FileReader(f);  BufferedReader br = new BufferedReader(fr);
String lin; while((lin=br.readLine())!=null){  con.append(lin).append("\n");  }
  return con.toString();
}

命名的级别的程序员,变量名完全是一时想到个什么字母单词之类的就敲出的,并且连注释也不写!这样人,阅读了他代码的连环杀手一定会让他死得很难看!

感觉写Ruby代码更是要如此,比如@posts表示你取出来的是一个文章列表,但是我的旁边的那个同事就不注意这些细节,他用@post(他英语不好,但是我觉得是他赖得去理这些)

还有一次是大家一起做一个rails项目,另一个同事做好了他那一块,我要接着在他做的页面中加一个功能,我看他页面中有一个@user,我看正合我用,就直接用,却出错了,找错误花了我好一些时间,原来@user实际上Company类型的,他为什么不直接用@company啊?现在我要用user,是@user.user,你们说,这代码看着像个什么啊? ORZ,他为什么这样写的,因为他做的那个功能叫搜索用户,在页面上显示的是用户的公司。ORZ,我是无语了。

说实话,用rails做项目,我出的错好多都是因为成员们命名不规范导致的,找到这些错误后,很无语...
3
3
分享到:
评论
10 楼 Scriptlet 2009-01-05  
不要非黑即白。
实践中当然要尽量使用有意义的类,变量和方法名称。同时加上一定的说明会显得更有条例。
假设你的论点成立“注视源代码表明你写的代码还不好“,但是”不注释源代码也不能表明你写的代码很好“。
9 楼 xuyao 2008-12-02  
估计你没看过jdk源代码
8 楼 liuqiang 2008-11-25  
犯了原则性的错误,代码注释是必须的,除非你用纯DSL
7 楼 acnono 2008-11-25  
项目大一点  是没有精力让你去读一行一行的代码的。面向对象的思想跟注释代码也有差不多的地方,每个人负责不同的地方,我拿过来你做的部分,我只需要知道它是干什么的,然后用它,没必要去根究它是怎么干事情的。  注释是必须的,读别人代码就会知道。
6 楼 ddandyy 2008-11-25  
再糟糕不过的逻辑.......

想当然的看问题.........
5 楼 elstage 2008-11-25  
如果是一些简单的代码,你写的好,当然可以不加注释。如果是一些复杂的或者难懂的,你还能指望别人光看代码能看明白吗?举个极端的例子,jdk的源程序,如果没有api文档,难道你去理解源程序?
4 楼 funcreal 2008-11-24  
基本的DRY原则。
Don't Repeat Yourself。
代码和注释是一种重复。容易造成以后改了代码而不改注释的问题。
我还见过更疯狂的观点,认为文档和代码也是一种重复,从某些角度来讲,是很有道理的。
3 楼 puroc 2008-11-24  
是的,你说的对。干净漂亮的代码,不是一下子就写出来的吧。项目紧急,人员紧缺的情况下,进度是不允许我对每行代码都斟酌再斟酌的。逻辑稍微复杂点的代码就先写个注释,以免以后重构的时候看不懂。 我为啥说欲言又止呢,我是感觉你说的有道理,但同时我也感觉,加点注释也没啥不好的。
2 楼 qichunren 2008-11-24  
puroc 写道

看完之后,有种欲言又止的感觉。说的有点儿道理。但我还是会在难于理解的地方加点注释。以免以后自己都看不懂。

你有这种感觉:怕自己看不懂
你对自己写的代码都有这种感觉,别说让其他人来看你写的代码了。
所以还是要努力,最起码的一条:可以让变量等富有语义,这点不是很难吧。
1 楼 puroc 2008-11-24  
看完之后,有种欲言又止的感觉。说的有点儿道理。但我还是会在难于理解的地方加点注释。以免以后自己都看不懂。

相关推荐

    源代码注释删除工具

    在描述中提到的"不想让非授权者查看软件源代码注释信息或者敏感信息",这表明了保护知识产权和商业秘密的重要性。源代码中的注释可能包含开发者的思考过程、设计决策以及潜在的安全漏洞信息。如果这些信息落入不法之...

    ssm整合源代码框架,内附注释

    这个压缩包中的源代码提供了一个完整的SSM整合示例,内附注释,便于理解和学习。 首先,Spring作为核心的依赖注入(DI)和面向切面编程(AOP)框架,为应用提供了灵活的控制层。Spring框架允许开发者管理对象及其...

    软著源代码整理工具

    "输入文件夹路径即可"表明该工具的使用非常简单,只需要提供包含源代码的文件夹路径,工具就会自动进行整理工作。 结合标签“软著源代码”和“源代码整理”,我们可以推测这个工具可能有以下功能: 1. **代码格式...

    Java代码注释率检查器.rar

    过低的注释率可能表明代码难以理解,而过高的注释率则可能意味着代码设计不够清晰,需要过多的解释。通常,行业标准建议的代码注释率在15%~30%之间,但这也会根据项目的具体需求和团队的约定有所不同。 使用注释率...

    SOC 系统 源代码

    3. 教程:这表明该源代码可能包含了示例、注释和指导,适合初学者或者开发者学习SOC系统的设计和实现。 【知识点详解】: 1. SOC系统架构:SOC系统通常包含中央处理器(CPU)、存储器(ROM、RAM)、数字信号处理器...

    源代码及注释行数统计工具

    源代码及注释行数统计工具是一款非常实用的软件,主要功能是对VB(Visual Basic)、C++、Java以及Delphi等编程语言的源代码进行分析,统计其中的代码行数和注释行数。这对于软件开发人员来说是极具价值的,因为了解...

    非常好的电磁炉源代码.zip

    【标签】"软件/插件 非常好的电磁炉源代码"表明这个项目不仅涉及到软件部分,还可能包含与硬件交互的组件,比如电磁炉的控制电路。软件部分可能是一个独立的应用程序,或者是运行在微控制器上的固件。"插件"这个词...

    linux-0.11 源代码+内核代码完全注释

    这个源代码包包含的是Linux-0.11的原始代码,并且附带了详细的内核代码注释,是学习和研究Linux内核的宝贵资料。 Linux内核是操作系统的核心部分,负责管理系统的硬件资源,如CPU、内存,以及提供系统调用接口供...

    代码注释检测工具,用于进行代码注释统计

    通常,注释与代码行的比例是一个衡量标准,过少的注释可能导致理解困难,过多则可能表明代码过于复杂,需要优化。一个健康的注释比例可以帮助保持代码的平衡,确保团队成员可以高效地阅读和理解代码。 此外,该工具...

    源代码统计工具挺好用的 喜欢的朋友们就试试

    标题中的“源代码统计工具挺好用的 喜欢的朋友们就试试”表明这是一个用于统计源代码相关数据的工具,可能包括代码行数、注释行数等。描述进一步揭示了该工具的功能,它能够分析VC(Visual C++)项目,提供关于代码...

    软著源代码整理工具,生成软著格式代码文本

    在软件开发过程中,源代码是程序员编写的指令集合,通常包含大量的注释、空格以及换行符,这些在申请软著时并不需要。此工具能够自动化地去除这些不必要的元素,以简洁、清晰的形式展示代码的核心逻辑,从而满足软著...

    JAVA_连连看_源代码行行注释

    《JAVA_连连看_源代码行行注释》 该程序是使用Java语言实现的一款连连看游戏,通过Myeclipse 8.51作为开发环境,兼容Windows XP、Windows 7等操作系统。游戏具备基本功能,如退出、重列、再来一局,适合在普通...

    飞思卡尔双核单片机的源代码及注释

    通过对这份源代码的学习,开发者不仅能提升对飞思卡尔双核单片机的使用技能,还能掌握更高级的嵌入式系统设计和优化技巧,这对于在相关领域发展是极其宝贵的。同时,结合实际项目练习,可以更好地将理论知识转化为...

    拖拉机游戏单机版源代码(带有详细的注释)

    标题提到的是"拖拉机游戏单机版源代码(带有详细的注释)",这表明我们讨论的是一款基于计算机的拖拉机游戏的源代码,它专为单人模式设计,并且源码中包含了丰富的注释。拖拉机游戏,也称为升级,是中国流行的扑克牌...

    java1.5 annotation注释源代码

    - **代码生成**:例如`@Generated`注解可以表明代码由代码生成工具生成。 - **元数据**:提供额外的信息,如`@Deprecated`标记不再推荐使用的API。 ### 5. 反射与注解 Java的反射API允许在运行时检查类、接口、...

    java 扫雷源代码 带有详细的注释

    9. **版本控制**:文件名4ed00833256643fb8ce417c8eeae5904可能是Git或其他版本控制系统中的哈希值,表明这个源代码版本是经过版本控制的,可以追踪代码的历史修改。 通过分析和学习这个Java扫雷源代码,开发者不仅...

    计算源代码行数源代码vc2005

    标题中的“计算源代码行数源代码vc2005”指的是一个使用Microsoft Visual C++ 2005(简称VC2005)开发的程序,它的主要功能是统计指定目录下源代码文件中的有效行数、空行数以及注释行数。这种工具在软件开发中非常...

    源代码使用说明_PowerPC;源代码使用_

    源代码使用_"这个标题表明我们将要探讨的是针对PowerPC架构的源代码使用和理解。PowerPC是一种高性能的精简指令集计算机(RISC)架构,广泛应用于嵌入式系统、服务器和工作站等领域,由IBM、Motorola和Apple共同开发...

    C/C++源程序去注释工具

    标题 "C/C++源程序去注释工具" 暗示了这个压缩包包含一个用于删除C或C++源代码中的注释的程序。这样的工具在特定情况下可能会有用,例如在进行代码分析、保密处理或者简化代码阅读时。C/C++编程语言允许开发者通过...

    C#编写的程序源代码管理器(源代码)

    “链接Access数据库”表明该源代码管理器将数据存储在Microsoft Access数据库中,这是一个轻量级的关系型数据库管理系统,适合小型项目和快速原型开发。使用数据库来存储源代码信息,可能包括项目名称、作者、版本、...

Global site tag (gtag.js) - Google Analytics