原文地址:
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做项目,我出的错好多都是因为成员们命名不规范导致的,找到这些错误后,很无语...
分享到:
相关推荐
winphone7源代码电话号码转发,程序中有注释表明了每句的含义。 一看就明了,特别简单,适合自学者和初学者。
为了解决这个问题,提出了一种基于源代码结构(如类名、方法名、变量名、注释等)信息和历史缺陷报告信息进行缺陷定位的方法,对于源代码结构的不同部分,在与缺陷报告进行词语匹配时,赋予它们不同的权重,同时充分...
* 代码干扰型:在源代码中加入死代码,作为困扰阅读者的干扰项增加阅读障碍,且不影响原来程序的执行。 3. 检测方法和反混淆算法 文章提出了改进的检测方法和反混淆算法,对javascript代码混淆进行检测和解混淆。...
非对称密码在加密和解密时,是把加密的数据当作一个大的正整数来处理,这样就涉及到大整数的加、减、乘、除和指数运算等,同时,还需要对大...要求源程序中有相应注释。 6.要求采用Visual C++ 6.0及以上版本进行调试。
该项目包含“皮肤病变分析的数据增强”中描述的所有实验的源代码。 抽象的 深度学习模型在自动皮肤病变分析中显示出显着的结果。 然而,这些模型需要大量数据,而带注释的皮肤病变图像的可用性通常是有限的。 数据...
本项目发明了一种新的基于视觉技术的教鞭幕布交互方法,利用教鞭在幕布上的移动和停顿等动作完成...内有详细的源代码,执行程序和研制报告.winxp+ppt2007+bcb6下测试通过,屏幕分辨率最好为1024*768(因为涉及到坐标变换)
基于源代码接口定义自动推导,强大的返回结构推导。支持Spring MVC、Spring Boot、Spring Boot Web Flux(controller书写方式)、Feign。支持Callable、Future、CompletableFuture等异步接口返回的推导。支持JavaBean...
MATLAB代码:含电热联合系统的微电网运行优化[火] 关键词:]微网 电热联合系统 优化调度 综合能源系统 仿真平台:MATLAB yalmip+cplex 主要内容:提出基于电热联合调度的区域并网型...代码非常精品,注释清楚,容易理解
QlikView 11 还具有与源代码控制系统集成的能力。当使用 QlikView Desktop 时此功能可用。文件菜单拥有新菜单选项,使 QlikView 开发者能连接 QlikView 文档至源代码控制系统。此项功能使用 XML 项目文件,QlikView ...
如果你是一个像我这样的自由软件作者,经常需要将源代码发布到网页上,这项功能能帮助你完成这个任务。转化后的HTML代码可以完整地保留颜色、样式、字体等,并且可以让你自己定制。 11. PE Information:文件头...
通过让另一个开发人员检查第一个开发人员编写的代码,可以在将代码提交到源代码管理之前发现并修复错误和不一致性。 代码审查的优点: 在提交代码之前就发现了错误-可以,不是所有的错误,但是很多。 在整个代码...
通过使用与 FiGAS 的源代码一起提供的专门词典,所提出的方法是完全不受监督的,并针对经济和金融领域进行定制。 我们的基于词典的 SA 方法依赖于一组详细的语义极性规则,可以根据 \textit{Interpretable AI} 的...
本实验报告通过阅读 Cache 模拟器源代码,了解直接映像、组相连映像、全相连映像以及数据组织与数据访问性能之间的关系。 Cache 体系结构的实验目的: 1. 了解 Cache 的三种映像规则:直接映像、组相连映像、全...
程序代码 程序代码 Create TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `userName` varchar(50) DEFAULT NULL, `userAge` int(11) DEFAULT NULL, `userAddress` varchar(200) DEFAULT NULL, ...
这些文件可以是例如其中具有单个或多个许可证的LICENSE文件,也可以是注释中带有许可证文本的源代码文件。 每个结果都与“可信度”相关联,表明匹配的接近程度。 置信度为1.0表示完全匹配,置信度为0.0表示没有许可...
解释是将源代码逐条转换成目标代码同时逐条运行目标代码的过程。 1.2.3计算机编程 我学习Python的原因: 通过编程实现自动化,提高效率。 通过编程了解一个新的广阔世界。 学习一门编程语言(重点在于练习) 掌握该...
2.程序源代码: #include "stdio.h" #include "conio.h" main() { long f1,f2; int i; f1=f2=1; for(i=1;i;i++) { printf("%12ld %12ld",f1,f2); if(i%2==0) printf("\n"); /*控制输出,每行四个*/ f1=f1+f2...
重要的是要注意,如果您是DIO平台的学生,那么最好检查一下代码并将其与您的解决方案进行比较,或者仅将源代码用作激发您创造力的灵感。 阅读重要声明和执行部分。 我不禁止在平台上使用我的代码,但这不会增加您...
这是一本免费的开放源代码教科书,旨在指导学生证明存在无法由部首解决的五次多项式。 它打算用于第二学期的本科抽象代数课程; 必要的背景知识可以在的(免费的,开放源代码的)教科书《。 与Dana的书一样,该书...
大二的课程设计 ...要求源程序中有相应注释; 5. 要求测试例子要比较详尽,各种极限情况也要考虑到,测试的输出信息要详细易懂,表明各个功能的执行正确; 6. 要求采用Visual C++ 6.0及以上版本进行调试;