在碼農(nóng)中有兩種人:程序員與好的程序員。也許我們從事編程工作已經(jīng)很多年了,并不是所有人都可以像稱職的好程序員那樣寫(xiě)出高效的代碼。下面是Mehreen Tahir在 他的博客里 總結(jié)出幾種不講碼德的壞習(xí)慣,給我們編程拖了后腿。
1.注釋凌亂
我們經(jīng)常被告知需要認(rèn)真在自己的代碼中加上注釋,使得其他人容易理解代碼的功能。但做的不合時(shí)宜,注釋反而顯得代碼更蠢。比如下面的例子:
/*
set the value of the number integer to 32
*/
int number = 32;
對(duì)于可以不言自明的編程代碼完全不必要畫(huà)蛇添足增加注釋。這些注釋被編譯器忽略掉,通常編程人員么會(huì)將其忽略。如果代碼已經(jīng)一目了然,你還會(huì)看這些注釋嗎?大學(xué)教授代碼編程的老師會(huì)講:“具有自釋性的代碼就是好的代碼。” 如果你的代碼本身復(fù)雜,難道覺(jué)得你可以只使用一兩句話就能夠解釋的明白嗎?
通常一個(gè)誤區(qū)就是認(rèn)為編寫(xiě)繁瑣代碼的人能夠通過(guò)注釋將它解釋很清楚。不過(guò),這并不是說(shuō)你永遠(yuǎn)不用寫(xiě)代碼注釋了。正確的做法就是在書(shū)寫(xiě)簡(jiǎn)介、緊湊、自釋性強(qiáng)的代碼同時(shí),懂得選擇合適的地方、合適的方法給出代碼注釋。比如下面的一個(gè)例子:
function addSetEntry(set, value) {
/*
Don't return `set.add` because it's not chainable in IE 11.
*/
set.add(value);
return set;
}
2.代碼過(guò)寬
是不是見(jiàn)過(guò)下面這樣的代碼?
for (int i = 0; i < 10; ++i) { if (i % 2 * 0) continue; array[i] += 2; }
看似上面代碼寫(xiě)的緊湊,但如不書(shū)寫(xiě)成下面代碼更加易讀:
for (int i = 0; i < 10; ++i)
{
if (i % 2 * 0) continue;
array[i] += 2;
}
3.膠合詞語(yǔ)
原文作者使用Agglutination來(lái)說(shuō)明在代碼簡(jiǎn)單將多個(gè)詞語(yǔ)連寫(xiě)在一起形成復(fù)雜的變量、函數(shù)名稱的臭習(xí)慣。比如下面的代碼:
public interface ConditionChecker
{
boolean checkCondition();
}
這個(gè)代碼就不如修改成下面的形式:
public interface Condition
{
boolean isTrue();
}
對(duì)比一下,就可以看出代碼的好壞。對(duì)于一些具有確定功能的函數(shù)名稱,比如對(duì)Exception的捕獲處理的函數(shù),實(shí)際上就不需要總是將后綴加上Exception:
- OverflowException
- IndexOutOfRangeException
- InvalidOperationException
將它們直接寫(xiě)成下面的形式更直接明了:
- Overflow
- IndexOutOfRange
- InvalidOperation
在任何時(shí)候省略冗余詞語(yǔ),可以形成更加高效的代碼。
4.欠抽象
在編程中的抽象(Abstraction)是指通過(guò)函數(shù)、類、庫(kù)來(lái)將復(fù)雜算法進(jìn)行封裝,對(duì)外提供簡(jiǎn)明使用接口。就像我們駕駛汽車,無(wú)需過(guò)多了解發(fā)動(dòng)機(jī)和傳統(tǒng)原理那樣。如果編程時(shí)代碼欠抽象,將過(guò)多的細(xì)節(jié)留給使用者,就像需要每位司機(jī)都需要懂得汽車工作原理那樣。比如下面的代碼:
If (profileByUserId.get(user.getId())
.containsKey(profile.getId())
{
……
}
除非有必要,實(shí)現(xiàn)函數(shù)調(diào)用的接口越簡(jiǎn)潔越好。比如下面的代碼就是的代碼更加優(yōu)雅易讀。
if (user.canView(profile))
{
……
}
5.上帝類
人們通常將過(guò)大的類(class)稱為上帝類,是指維護(hù)了太多的功能,違反了單一職責(zé)原則,連上帝都看不懂你的代碼。
一般一個(gè)類同時(shí)滿足以下3個(gè)條件就是上帝類:
(1)CPFD (Capsules Providing Foreign Data) 從多個(gè)不相關(guān)類(模塊)中引用數(shù)據(jù)。
(2)WOC (Weighted Operation Count) 類的所有函數(shù)的圈復(fù)雜度之和超過(guò)65。
(3)TCC (Tight Capsule Cohesion) TCC < 1/3 類需要具有低內(nèi)聚的特性(類中直接相關(guān)的方法與全部方法之比小于1/3),也就是較少的private方法。
為什么編寫(xiě)上帝類是壞的碼德呢?這是因?yàn)檫^(guò)大的類往往會(huì)有很多重復(fù)代碼,且被子類繼承時(shí)也會(huì)造成大量?jī)?nèi)存浪費(fèi)。
6.拷貝粘貼
重復(fù)代碼一般是由于復(fù)制粘貼造成的。需求迭代過(guò)程中為了不影響已有功能,通常是將別人代碼copy一份改改。這種壞毛病最大弊端是最直接的弊端就是如果你想修改一段代碼邏輯,可能會(huì)遺漏,甚至需要多次修改才能確保全部修改完。當(dāng)然,那種只是拷貝粘貼,連代碼都不審查的做法更是人神共憤了。
7.過(guò)長(zhǎng)的參數(shù)
全局變量是個(gè)邪惡的東西,數(shù)據(jù)是共享的并且每個(gè)線程都可以修改,太多了容易導(dǎo)致程序不可控,所以大家喜歡將變量以行參的方式傳遞,久而久之參數(shù)列越來(lái)越長(zhǎng)了。
為什么過(guò)長(zhǎng)參數(shù)列是一種不好的碼德呢?
方法參數(shù)的數(shù)量太多會(huì)導(dǎo)致代碼可讀性非常差,如果有多個(gè)重載方法它們的方法參數(shù)都非常多,在寫(xiě)代碼時(shí)很難判斷該調(diào)用哪一個(gè)。當(dāng)一個(gè)方法需要新增功能,每次都可能會(huì)新增一個(gè)方法參數(shù),這樣導(dǎo)致調(diào)用方每次都要重新適配,小心被打哦,耗子尾汁。
那么,當(dāng)參數(shù)過(guò)長(zhǎng)怎么辦?可以使用一個(gè)數(shù)據(jù)傳輸對(duì)象來(lái)進(jìn)行傳輸?;蛘呖紤]重構(gòu)函數(shù)來(lái)解決過(guò)長(zhǎng)參數(shù)傳遞。
8.虛榮的預(yù)留特性
有的時(shí)候會(huì)聽(tīng)到合作開(kāi)發(fā)的小伙伴夸夸其談,講什么在設(shè)計(jì)程序代碼中預(yù)留了擴(kuò)展性,但這些擴(kuò)展特性在當(dāng)下實(shí)屬聾子的耳朵-擺設(shè)。關(guān)鍵這種預(yù)留擴(kuò)展特性 一旦成為風(fēng)氣,過(guò)度的抽象和預(yù)留擴(kuò)展最終可能會(huì)讓軟件代碼難以理解,提前背上包袱,使得軟件開(kāi)發(fā)變得復(fù)雜,進(jìn)展速度慢下來(lái)。
此時(shí),需要堅(jiān)持簡(jiǎn)單設(shè)計(jì)原則(Simple Design),刪除那些覺(jué)的可能未來(lái)有用的參數(shù)、代碼、調(diào)用等。
如果代碼的改動(dòng)確實(shí)是未來(lái)必然會(huì)發(fā)現(xiàn)的,那么還是建議保留??淇淦湔勎磥?lái)性更多是指開(kāi)發(fā)人員無(wú)依據(jù)臆測(cè)未來(lái),導(dǎo)致代碼模塊被過(guò)度設(shè)計(jì)。
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問(wèn)題,請(qǐng)聯(lián)系我們,謝謝!