热门标签 | HotTags
当前位置:  开发笔记 > 数据库 > 正文

美化java代码,从合理注释开始

在Java的编写过程中我们需要对一些程序进行注释,除了自己方便阅读,更为别人更好理解自己的程序,可以是编程思路或者是程序的作用,总而言之就是方便自己他人更好的阅读。下面我们来一起学习一下吧

请停止代码注释

“干净的代码应该像写好的散文一样” - Robert C. Martin

不良代码的通病就是有很多注释。这是凌乱的源代码最明显的迹象。

每个程序员的目标应该是编写干净和富有表现力的代码,以避免代码注释。每个变量,函数和类的目的应该隐含在其名称和结构中。

当其他人读取您的代码时,他们不应该阅读注释以了解你的代码正在做什么。命名良好的类和函数应该引导读者通过你的代码,就像一本写得很好的小说一样。当读者看到一个新的类或功能时,他们不应该对他们在里面看到的东西感到困惑难以理解。

请记住,开发人员的工作时间很少花在编写代码上,花在阅读代码和理解代码上的时间要多得多。

注释掩饰错误

在代码中命名是非常重要的。您应该花费大量精力准确而精确地命名每一段代码,以便其他开发人员能够理解您的代码。

// 按状态查找员工
List find(Status status) {
...
}

在此示例中,名称find不够描述,因此此函数的作者需要留下描述函数功能的描述性注释。当我们看到从另一个模块调用的find函数时,它的作用是一个谜。它发现了什么?究竟是什么意思?它返回了它发现的东西吗?怎么找到它发现的东西?就像鲍勃叔叔在他的书《Clean Code》中所说,如果你需要写注释,你就无法通过代码表达自己真实的用意。

我们不希望检查每个函数上面的注释,以了解它的作用。

List getEmployeesByStatus(Status status) {
...
}

现在很明显能看出来这个函数的具体作用,这使得注释变得多余。这让我想到了注释糟糕的下一个方式。

冗余注释

这些混乱了你的代码,完全没必要。

//此函数发送电子邮件
void sendEmail() {
...
}
//此函数发送电子邮件
public class Employee {
...
}
/ **
* @param title CD的标题
* @param作者CD的作者
* @param track CD上的曲目数
* /
public void addCd(String title, String author, int tracks) {
...
}

多数情况是强制冗余。很多公司在每个功能和类别上都要求这一点。如果你的上司要求这样做,请他们不要。

错误的抽象程度

如果您有一个很长的功能或需要记录代码的哪一部分做了什么,那么您可能违反了这些规则:

1.功能应该做一件事。

2.功能应该很小。

这是一个例子

//此函数计算价格,与销售额进行比较
//促销,检查价格是否有效,然后
//向用户发送促销电子邮件
public void doSomeThings(){
//计算价格
...
...
...

//将计算出的价格与促销活动进
...
...
...

//检查计算的价格是否有效
...
...
...

//向用户发送促销信息
...
...
...
}

当你成功地将逻辑的每个部分封装到一个单独的函数中时,代码不需要注释就会表现的应该像它的作用描述一样。

重构如下:

public void sendPromotionEmailToUsers(){
calculatePrices();
compareCalculatedPricesWithSalesPromotions();
checkIfCalculatedPricesAreValid();
sendPromotionEmail();
}

而不是注释代码的每个部分,每个逻辑块应该很好地封装在它自己的函数中。

首先,这提高了可读性。每个代码块不必逐行读取。我们可以简单地读取辅助函数名称并理解它的作用。如果我们想要了解每个函数内部的更多细节,就能去看具体实现。

其次,它提高了可测试性。在上面的示例中,我们可以为每个函数单独进行单元测试。如果不封装这些单独的函数,则很难测试较大函数sendPromotionEmailToUsers()的每个部分。执行多个功能的功能很难测试。

最后,它提高了可重构性。通过将逻辑的每个部分封装到自己的函数中,将来更改维护更容易,并且单独功能的函数会被隔离以仅更改该函数的行为。当我们使用局部变量的长函数在整个函数中持续存在时,由于函数的紧耦合,很难在不导致其他地方变化的情况下重构函数。

注释掉的代码

注释掉的代码应该被视为roadkill。不要看它,不要闻它,不要问它从哪里来,只是摆脱它。保持它的时间越长,其余代码闻到的时间就越长......

/ *
public void oldFunction(){
noOneRemembersWhyIAmHere();
tryToUnCommentMe();
iWillProbablyCauseABuildFailure();
HAHAHA();
}
* /

尽管删你不删别人更不敢删。如果你以后需要它,你可以随时检查版本控制系统,因为你肯定用了VCS,对吗?(如果不是当我没说)

TODO注释

不要写TODO注释,而不仅仅是......做到了吗?大多数时候这些注释都会被遗忘,后来可能变得无关或错误。当另一个程序员稍后看到TODO注释时,他们如何知道是否还需要这样做?

不过偶尔TODO注释是好的,如果你正在等待另一个队友的合并(一般不会太久)。就可以这么做,直到你可以进行修复并提交它。

“当你觉得有必要写注释时,首先要尝试重构代码,以便任何注释都变得多余。” - Martin Fowler

注释的谎言

当Jimmy在他写的新功能上面打上注释时,他认为他正在帮助任何看到他的代码的未来开发人员。其实呢他真正在做的是设置一个陷阱。他的注释可能是弥天大谎(没有双关语意图)蛰伏数月或数年没有被触及,只是等待成为一个令人讨厌的陷阱。然后有一天,在数百个重构和需求变更之一中,他的注释从一些遥远的模块中失效,但是仍然在错误的引导着无数的接盘侠。

当你更改一行代码时,你怎么知道你更改的代码会不会使其他地方的注释无效?没有办法知道

public class User {
...
//它包含用户的名字和姓氏
String name;
...
}

然后,需求更改,他们希望将名称拆分为firstName和lastName。

public class User {
...

// 它包含用户的名字和姓氏
String firstName;
String lastName;

...
}

注释现在已经错了。你可以更新注释以反映更改,但是你是否真的想在每次更改后手动维护所有注释?你是开发人员,而不是文档。

但是这个注释很容易被注意到并且没有问题需要改变。但是你很难保证在程序的其他地方,会不会也注释了这个参数name是用户的名字和姓氏。更改一小块地方的代码,可能会让很多的代码注释都失效。

让我们看另一个例子:

//根据状态处理员工
void processEmployees(){
...
List  employees = findEmployees(statusList);
...
}

//这会按状态列表查找Employees
List  findEmployees(List  statusList){
...
}

然后有人被要求更改函数findEmployees,以便通过名称列表而不是状态列表查找员工。

//根据状态处理员工
void processEmployees(){
...
List  employees = findEmployees(statusList);
...
}

//这会按状态列表查找Employees
List  findEmployees(List  nameList){
...
}

首先,上面的注释findEmployees已经失效,因此需要更改。没问题,对吧?错了。

processEmployees上面的注释也已失效,因此也需要更改。还有多少其他评论被这个小型重构改成无效?这一次更改在源代码中创建了多少注释谎言?

替代方案:

void processEmployees(){
...
List  employees = findEmployeesByName(nameList);
...
}

List  findEmployeesByName(List  nameList){
...
}

如果你准确而准确地命名你的函数,则不需要注释,并且你不会在代码中散布谎言。

“代码永远不会说谎,注释会。” - 罗恩杰弗里斯

什么时候需要注释呢

我知道很多开发人员都是代码注释的死硬支持者,对他们来说,我必须承认有时注释是可以的。不过你每写一段都应当有充足的理由

复杂表达式

如果您有复杂的SQL或正则表达式语句,请继续编写注释。在代码中干净利落地表达诸如此类的陈述可能很困难。在这些表达式上面添加注释可以帮助其他开发人员更好地理解您的代码。

// 格式匹配kk:mm:ss EEE,MMM dd,yyy
Pattern timePattern = Pattern.compile("\\d*:\\d*:\\d* \\w*, \\w*, \\d*, \\d*");

注释警告

如果你需要警告其他开发人员这段代码可能发生的bug,可以在此代码附近留下注释。这些注释可以充当代码中神秘行为的先兆,并为你的代码增加价值。

意图澄清

如果你实在命名废,那就要为你没有能力写出富有表现力的代码而负责,并写下注释表明自己的意图。

如果你必须撰写注释,请确保它是本地的。远离其引用的非本地评论注定会失效并变成谎言。引用函数或变量的注释应直接位于其上方。警告注释可以在它引用的代码的上方或旁边。如果您的IDE支持注释突出显示,请使您的警告注释从其余代码中脱颖而出。

最后

我已经建立了对代码注释的感受。我鄙视他们,但我知道有时他们是需要的。

所以,请停止写这么多注释。

本文是作者在推特上看到国外一位大神 布莱恩·诺兰德 的论述,深以为然因此翻译后加以修饰进行分享的。希望今后自己的代码也能像散文一样优雅。


推荐阅读
  • 一、Hadoop来历Hadoop的思想来源于Google在做搜索引擎的时候出现一个很大的问题就是这么多网页我如何才能以最快的速度来搜索到,由于这个问题Google发明 ... [详细]
  • 推荐一个ASP的内容管理框架(ASP Nuke)的优势和适用场景
    本文推荐了一个ASP的内容管理框架ASP Nuke,并介绍了其主要功能和特点。ASP Nuke支持文章新闻管理、投票、论坛等主要内容,并可以自定义模块。最新版本为0.8,虽然目前仍处于Alpha状态,但作者表示会继续更新完善。文章还分析了使用ASP的原因,包括ASP相对较小、易于部署和较简单等优势,适用于建立门户、网站的组织和小公司等场景。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 本文介绍了如何在MySQL中将零值替换为先前的非零值的方法,包括使用内联查询和更新查询。同时还提供了选择正确值的方法。 ... [详细]
  • 本文介绍了如何使用Power Design(PD)和SQL Server进行数据库反向工程的方法。通过创建数据源、选择要反向工程的数据表,PD可以生成物理模型,进而生成所需的概念模型。该方法适用于SQL Server数据库,对于其他数据库是否适用尚不确定。详细步骤和操作说明可参考本文内容。 ... [详细]
  • 在数据分析工作中,我们通常会遇到这样的问题,一个业务部门由若干业务组构成,需要筛选出每个业务组里业绩前N名的业务员。这其实是一个分组排序的 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • Oracle Database 10g许可授予信息及高级功能详解
    本文介绍了Oracle Database 10g许可授予信息及其中的高级功能,包括数据库优化数据包、SQL访问指导、SQL优化指导、SQL优化集和重组对象。同时提供了详细说明,指导用户在Oracle Database 10g中如何使用这些功能。 ... [详细]
  • 本文介绍了adg架构设置在企业数据治理中的应用。随着信息技术的发展,企业IT系统的快速发展使得数据成为企业业务增长的新动力,但同时也带来了数据冗余、数据难发现、效率低下、资源消耗等问题。本文讨论了企业面临的几类尖锐问题,并提出了解决方案,包括确保库表结构与系统测试版本一致、避免数据冗余、快速定位问题等。此外,本文还探讨了adg架构在大版本升级、上云服务和微服务治理方面的应用。通过本文的介绍,读者可以了解到adg架构设置的重要性及其在企业数据治理中的应用。 ... [详细]
  • C语言注释工具及快捷键,删除C语言注释工具的实现思路
    本文介绍了C语言中注释的两种方式以及注释的作用,提供了删除C语言注释的工具实现思路,并分享了C语言中注释的快捷键操作方法。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 本文介绍了使用postman进行接口测试的方法,以测试用户管理模块为例。首先需要下载并安装postman,然后创建基本的请求并填写用户名密码进行登录测试。接下来可以进行用户查询和新增的测试。在新增时,可以进行异常测试,包括用户名超长和输入特殊字符的情况。通过测试发现后台没有对参数长度和特殊字符进行检查和过滤。 ... [详细]
  • 本文详细介绍了MysqlDump和mysqldump进行全库备份的相关知识,包括备份命令的使用方法、my.cnf配置文件的设置、binlog日志的位置指定、增量恢复的方式以及适用于innodb引擎和myisam引擎的备份方法。对于需要进行数据库备份的用户来说,本文提供了一些有价值的参考内容。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • 本文由编程笔记小编整理,介绍了PHP中的MySQL函数库及其常用函数,包括mysql_connect、mysql_error、mysql_select_db、mysql_query、mysql_affected_row、mysql_close等。希望对读者有一定的参考价值。 ... [详细]
author-avatar
青岛新侨妙妙
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有