前言
今天跟大家聊一个有趣的话题:如何写出让人抓狂的代码?
大家看到这个标题,第一印象觉得这篇文章可能是一篇水文。但我很负责的告诉你,它是一篇有很多干货的技术文。
曾几何时,你在阅读别人代码的时候,有没有抓狂,想生气,想发火的时候?
今天就跟大家一起聊聊,这20种我看了会抓狂的代码,看看你中招了没?
1.不注重代码格式
代码格式说起来很虚,下面我用几个案例演示一下,不注重代码格式的效果。作为这篇文章的开胃小菜吧。
1.1 空格
有时候必要的空格没有加,比如:
@Service
@Slf4j
public class TestService1{
public void test1(){
addLog("test1");
if (condition1){
if (condition2){
if (condition3){
log.info("info:{}",info);
}
}
}
}
}
复制代码
你看了这段代码有何感想,有没有血压飙升的感觉?
代码好像揉到一起去了。
那么,如何把血压降下来呢?
答:加上空格即可。
正解:
@Service
@Slf4j
public class TestService1 {
public void test1() {
addLog("test1");
if (condition1) {
if (condition2) {
if (condition3) {
log.info("info:{}", info);
}
}
}
}
}
复制代码
只加了一些空格,稍微调整了一下,这段代码的层次结构一下子变得非常清晰了。
好吧,我又冷静下来了。
1.2 换行
写代码时,如果有些必要的换行没有加,可能会出现这样的代码:
public void update(User user) {
if (null != user.getId()) {
User oldUser = userMapper.findUserById(user.getId());
if(null == oldUser)throw new RuntimeException("用户id不存在");
oldUser.setName(user.getName());oldUser.setAge(user.getAge());oldUser.setAddress(user.getAddress());
userMapper.updateUser(oldUser);
} else { userMapper.insertUser(user);
}
}
复制代码
看了这段代码,是不是有点生无可恋的感觉?
简单的加点空格优化一下:
public void update(User user) {
if (null != user.getId()) {
User oldUser = userMapper.findUserById(user.getId());
if(null == oldUser) {
throw new RuntimeException("用户id不存在");
}
oldUser.setName(user.getName());
oldUser.setAge(user.getAge());
oldUser.setAddress(user.getAddress());
userMapper.updateUser(oldUser);
} else {
userMapper.insertUser(user);
}
}
复制代码
代码逻辑一下子变得清晰了许多。
2.随意的命名
java中没有强制规定参数、方法、类或者包名该怎么起名。但如果我们没有养成良好的起名习惯,随意起名的话,可能会出现很多奇怪的代码。
2.1 有意义的参数名
有时候,我们写代码时为了省事(可以少敲几个字母),参数名起得越简单越好。假如同事A写的代码如下:
int a = 1;
int b = 2;
String c = "abc";
boolean b = false;
复制代码
一段时间之后,同事A离职了,同事B接手了这段代码。
他此时一脸懵逼,a是什么意思,b又是什么意思,还有c...然后心里一万个不爽。
给参数起一个有意义的名字,是非常重要的事情,避免给自己或者别人埋坑。
正解:
int supplierCount = 1;
int purchaserCount = 2;
String userName = "abc";
boolean hasSuccess = false;
复制代码
2.2 见名知意
光起有意义的参数名还不够,我们不能就这点追求。我们起的参数名称最好能够见名知意
,不然就会出现这样的情况:
String yongHuMing = "苏三";
String 用户Name = "苏三";
String su3 = "苏三";
String suThree = "苏三";
复制代码
这几种参数名看起来是不是有点怪怪的?
为啥不定义成国际上通用的(地球人都能看懂)英文单词呢?
String userName = "苏三";
String susan = "苏三";
复制代码
上面的这两个参数名,基本上大家都能看懂,减少了好多沟通成本。
所以建议在定义不管是参数名、方法名、类名时,优先使用国际上通用的英文单词,更简单直观,减少沟通成本。少用汉子、拼音,或者数字定义名称。
2.3 参数名风格一致
参数名其实有多种风格,列如:
//字母全小写
int suppliercount = 1;
//字母全大写
int SUPPLIERCOUNT = 1;
//小写字母 + 下划线
int supplier_count = 1;
//大写字母 + 下划线
int SUPPLIER_COUNT = 1;
//驼峰标识
int supplierCount = 1;
复制代码
如果某个类中定义了多种风格的参数名称,看起来是不是有点杂乱无章?
所以建议类的成员变量、局部变量和方法参数使用supplierCount,这种驼峰风格
,即:第一个字母小写,后面的每个单词首字母大写。例如:
int supplierCount = 1;
复制代码
此外,为了好做区分,静态常量建议使用SUPPLIER_COUNT,即:大写字母
+
下划线
分隔的参数名。例如:
private static final int SUPPLIER_COUNT = 1;
复制代码
3.出现大量重复代码
ctrl + c
和 ctrl + v
可能是程序员使用最多的快捷键了。
没错,我们是大自然的搬运工。哈哈哈。
在项目初期,我们使用这种工作模式,确实可以提高一些工作效率,可以少写(实际上是少敲)很多代码。
但它带来的问题是:会出现大量的代码重复。例如:
@Service
@Slf4j
public class TestService1 {
public void test1() {
addLog("test1");
}
private void addLog(String info) {
if (log.isInfoEnabled()) {
log.info("info:{}", info);
}
}
}
复制代码
@Service
@Slf4j
public class TestService2 {
public void test2() {
addLog("test2");
}
private void addLog(String info) {
if (log.isInfoEnabled()) {
log.info("info:{}", info);
}
}
}
复制代码
@Service
@Slf4j
public class TestService3 {
public void test3() {
addLog("test3");
}
private void addLog(String info) {
if (log.isInfoEnabled()) {
log.info("info:{}", info);
}
}
}
复制代码
在TestService1、TestService2、TestService3类中,都有一个addLog方法用于添加日志。
本来该功能用得好好的,直到有一天,线上出现了一个事故:服务器磁盘满了。
原因是打印的日志太多,记了很多没必要的日志,比如:查询接口的所有返回值,大对象的具体打印等。
没办法,只能将addLog方法改成只记录debug日志。
于是乎,你需要全文搜索,addLog方法去修改,改成如下代码:
private void addLog(String info) {
if (log.isDebugEnabled()) {
log.debug("debug:{}", info);
}
}
复制代码
这里是有三个类中需要修改这段代码,但如果实际工作中有三十个、三百个类需要修改,会让你非常痛苦。改错了,或者改漏了,都会埋下隐患,把自己坑了。
为何不把这种功能的代码提取出来,放到某个工具类中呢?
@Slf4j
public class LogUtil {
private LogUtil() {
throw new RuntimeException("初始化失败");
}
public static void addLog(String info) {
if (log.isDebugEnabled()) {
log.debug("debug:{}", info);
}
}
}
复制代码
然后,在其他的地方,只需要调用。
@Service
@Slf4j
public class TestService1 {
public void test1() {
LogUtil.addLog("test1");
}
}
复制代码
如果哪天addLog的逻辑又要改了,只需要修改LogUtil类的addLog方法即可。你可以自信满满的修改,不需要再小心翼翼了。
我们写的代码,绝大多数是可维护性的代码,而非一次性的。所以,建议在写代码的过程中,如果出现重复的代码,尽量提取成公共方法。千万别因为项目初期一时的爽快,而给项目埋下隐患,后面的维护成本可能会非常高。
4.从不写注释
有时候,在项目时间比较紧张时,很多人为了快速开发完功能,在写代码时,经常不喜欢写注释。
此外,还有些技术书中说过:好的代码,不用写注释,因为代码即注释
。这也给那些不喜欢写代码注释的人,找了一个合理的理由。
但我个人觉得,在国内每个程序员的英文水平都不一样,思维方式和编码习惯也有很大区别。你要把前人某些复杂的代码逻辑真正搞懂,可能需要花费大量的时间。
我们看到spring
的核心方法refresh
,也是加了很多注释的:
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for