java代码质量_怎样才能写出漂亮高质量的java代码?

强烈推荐参阅《代码整洁之道》这本书,通过结合这本书的理论和技巧,在写代码的过程中不断重构,优化,你的代码质量就会逐步提高。以下是我参阅这本书之后总结出来的写出高质量代码的关键要点,你可以参考,希望能够帮助到你。

一以贯之的命名原则:

如fetch,get,retrieve 都可以用作获取,拿到 的意思,但是我们要根据实际的应用场景,在通一个类或者模块中尽量只使用其中一个作为方法名的前缀,如getXXX

一词一意原则:

如add表示增加,可以在任何地方增加,如前面,中间,后面等等。但是如果有一个方法需要表示只能在末尾附加,此时就不应该使用add方法了,而应该用append方法,这个原则给一以贯之命名原则做了限定,即只有是代表同样的操作的时候才一以贯之。

使用解决方案领域名称:

尽量使用专业的领域名称

使用源自所涉问题领域的名称:

当程序员很难在现有代码中使用专业领域名称的时候,可以考虑使用源自所涉问题领域的名称,可以理解为业务,了解业务,对于命名也是非常有帮助。

其实好的程序员和软件设计师,所做的工作就是分离好解决方案领域和问题领域的概念,使得代码更加贴近于问题领域

好的函数命名---只做一件事

如果一个函数里面,包含了同一个抽象层级的多个函数,这样也是算只做一件事,但是如果包含了不同抽象层级的,那就是做了很多事,多年的编码经验告诉我们,函数只做一件事,比做很多事好维护的多!

如何保证函数只做一件事

首先是这样的,把做的事情进行分解,比如说 可以这样来进行分解:

要做一个到大功能x ,就要先做第一个中等功能xx,要做一个中等功能xx就得先做一个小功能xxx。然后做第二个中等功能yy,要做中等功能yy,就要先做小功能yyy........通过一层层分解,就能保证函数只做一件事了。

函数的参数尽量少

函数的参数和函数名不是一个抽象层级上的东西,会让别人阅读的时候感觉有点困难,在一个函数中尽量不要使用参数,或者只有一个参数,要是3个以上的参数,那确实有点多了,除非特别必要,不然真的不要写那么多参数,太多了 让人容易误解。还有一个非常值得注意的是不要使用参数作为返回值!!!一定要使用函数返回值,不然真的让人很难读懂你的代码!

一元函数的普遍形式

向函数传入单个参数,有两种普遍理由,第一种,如boolean fileExists(“myFile”),这种是判断输入参数 是什么,怎么了,等等。。第二种,如InputStream fileOpen(“myFile”),这种是把参数转换为某种其他的东西,再输出来! 这个是书写一元函数普遍需要遵循的原则,值得注意的是,如果函数需要对输入函数进行转换的时候,转换结果应该体现在函数的返回值上,而不是参数

函数的参数里面不要放标识参数(即boolean)

因为函数里面放了标识参数,那么该函数做的事情就不是一件事了,它必须要判断当标识参数是真的时候,该做xxx,当标识参数为false的时候,该做yyy,在这种情况下,由于它要做很多的事,所以很难给她命名!例如这个函数 render(boolean isSuit); 当读者看到调用该函数的代码时,render(true) 根本不知道这是干嘛的!正确的做法是应该把他们拆开成两个函数,如 renderForSuit() 和 renderForNoSuit() 这样 就一目了然。一个小经验,当给一个类或者函数,变量命名时感觉非常困难的时候,往往意味着我们分析,划分的模块有问题,粒度不够小,模块和模块,函数和函数之间有 很大的耦合,还需要我们再仔细分析,划分,设计!

参数对象的抽取

如果一个函数拥有两个及以上的参数时,往往可以意味着,其中的一些参数可以封装成对象了,因为这些参数是一起传递到函数里面的,所以有很大的可能性,这些参数本身就有关系,所以把他们封装成对象就是很自然的做法了!例如:

MakeCircle(int x,int y,int radius);

可以改造成

MakeCircle(Point point , int radius);

这样就把x,y封装到一个对象去了,对代码的可读性有所提升!

函数命名--动词与关键字

较好的函数命名可以让使用我们代码的人很容易理解我们的代码,对于一元函数,应该使用动词+关键词(应该是名词)的组合形式,如 write(name)这个函数,相当令人认同,但是如果使用writeField(name)也许会更好,即动词+关键词的组合。再比如 assertEqual(expected,actual) 这个方法,改成assertExpectedEqualActual(expected,actual)也许会更好,这样别人再使用我的代码的时候就不用记住参数顺序啦!(不过我对此表示怀疑,因为现代的IDE是可以提示函数参数的,所以为了让函数名体现参数而写这么长的函数名,恐怕有点得不偿失,并且参数函数名+里面的参数已经体现了这个函数的意图,所以看起来也比较容易读!这个暂时放一边吧,没准以后再读的时候就不一样了)

函数不应该有副作用

例如一个函数

checkPassWord(userName,passWord){

If(userName.equals(“zrc”) && passWord.equals(“123”)){

This.initSession();

Return true; }

Else {

Return false;

}

}

这个函数虽然名为checkPassWord ,意思是检查用户的密码,实则它不只是干了这么一件事,它还干了一件事是重新初始化Session,这显然是不可以的,因为当别人接手你的代码的时候,要是相信了你这个函数的命名,认为它只是检查密码而已,不知道这背后的还有一个副作用是重新初始化Session,那么就有可能丢失Session数据,这肯定是不可以接受的,所以 正确的做法应该是把这个副作用提出去,如果确实要重新初始化Session,那就老老实实搞在这个函数后面写就是了!

分隔指令与询问

函数要么做什么事,要么回答是什么事,二者不可兼得,要是两个都做往往会做的很混乱

如下面这些语句

If(set(“userName”,”zrc”){

doXXXX

}

这个 乍一看,还真不太清楚想表达什么? 这个set函数返回值代表什么?是代表判断设置属性username成功与否的标识?还是判断username 之前的值是否是zrc的标识呢?

不清楚,

更好的做法是如下:

If(attributeExist(“username”)){

Set(“username”,”zrc”);

doXXX

}

这样就一目了然了!

使用异常代替返回错误码

如下代码:

If(deletePage(page) == E_OK){

If(deleteHeader(page.header) == E_OK){

}else{

//做对应的处理

}

}else{

//做 对应的处理

}

使用错误码返回 会导致代码里面充满着if else 的判断。不利于代码的阅读

正确的做法是 使用异常来处理这些

如下代码:

Try{

deletePage(page);

deleteHeader(page.header);

}

Catch(e){

//做响应的处理

}

这样的代码就把错误的处理信息从代码的主路径中抽离出来,更加容易阅读!

错误处理只是一件事,抽离出try/catch代码块

如函数:

Void delete(page){

Try{

deletePage(page);

deleteHeader(page.header);

}

Catch(e){

//做响应的处理

In.close();

}

}

其实这个函数还不是最好的,毕竟delete 这个函数做了 删除了page和header 这件事之外,还做了一件判断异常的事情,违反了一个函数只做一件事的原则,所以可以把他们抽取出来如下:

Void delete(page){

Try{

deletePageAndHeader(page);

}

Catch(e){

//做响应的处理

handlerException();

}

}

Void deletePageAndHeader(page){

deletePage(page);

deleteHeader(page.header);

}

Void handlerException(){

In.close();

}

经过这样的抽离之后,就可以看出 代码写的很优雅了!相当于delete函数只干一件事,就是判断是否有异常

最后再说一下,写代码其实跟写其他东西是一样的,就像写文章一样,你先想什么就写什么,然后再打磨它,初稿可能粗陋无序,那你就仔细斟酌,直到达到你心中的样子。

一开始乱很正常,但是要在后续不断的斟酌,思考,重构出你想要的样子,写代码不是一开始就按照规则来的,我想应该没人能做到,只有不断地写,不断地发现重复,不断打磨重构才能写出好的代码!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值