好的代碼會說話-代碼整潔之道

《代碼整潔之道》總結(jié)

我們需要寫出整潔的代碼嗎

我是個6年開發(fā)經(jīng)驗的java程序員,在我的職業(yè)生涯中陕贮,看到過不少讓產(chǎn)生罵人沖動的代碼偶妖,當(dāng)然也寫過讓別人讓別人想罵人的代碼??。我曾很多次想改進(jìn)的我的代碼風(fēng)格找默,想讓它們更易懂,更嚴(yán)謹(jǐn)吼驶,更整潔惩激,更高效。但是終究還是寫了很多爛代碼旨剥。我總結(jié)了寫爛代碼的原因:

  • 1咧欣、活多、時間緊轨帜。這可能是我們多數(shù)程序員寫爛代碼的直接原因魄咕,我們總抱怨需求緊時間少,功能實現(xiàn)就不錯了蚌父,哪管代碼的好賴哮兰,或許這只是一個接口毛萌,真正的原因是我們懶于思考。如何去改進(jìn)代碼風(fēng)格喝滞。一個需求我們寫代碼的時間往往只占一小部分阁将,就我個人而言,如果一個一天工作量的需求我寫代碼的時間往往不到2個小時右遭。更多的時間一部分是搞清楚需求做盅,另外一部分時間是和各種聯(lián)調(diào)測試,當(dāng)然還有同事隨時來找我打斷我的工作窘哈,重新開始寫時就需要重新 理下寫代碼思路吹榴。如果是修改之前的功能那耗費(fèi)最多時間的那就是閱讀這個功能之前的代碼。不管是調(diào)試代碼還是閱讀代碼滚婉,代碼的可讀性至關(guān)重要,易讀才是寫代碼高效的關(guān)鍵图筹。多抽象出一個公用方法,變量名起的更貼切易懂寫真的占用很多時間嗎?好吧這些確實要占用你幾分鐘但當(dāng)你調(diào)試或者修改時或許可以幫你省下幾個小時.

  • 2让腹、老代碼多人經(jīng)手無力回天远剩。這種情況我也遇到過很多,但是當(dāng)我們放任這種情況不管骇窍,那這些代碼只能越來越糟瓜晤、越來越難以維護(hù),最終變得不可維護(hù)像鸡。這種情況如果我們沒有足夠的信心去重構(gòu)一些方法活鹰,那我們至少需要讓 "讓營地比你來時更干凈"哈恰, 讓代碼簽入時比簽出時更干凈只估。

  • 3、我也想寫出漂亮干凈的代碼着绷,但是缺乏整體風(fēng)格蛔钙,想一出是一出,難以為繼荠医。這種情況也較為多見吁脱,什么叫整潔的代碼,每個人理解不一樣彬向,一千個程序員就有一千種對好代碼的理解兼贡。我的理解是寫出最多人更易讀懂的代碼就是好代碼。因為代碼更多是被讀的娃胆。不管是代碼的作者自己還是別的程序員遍希。

基于以上我認(rèn)為整潔的代碼應(yīng)該是一個好程序員的基本素質(zhì)。那么如何寫出整潔的代碼呢里烦?以下是我在讀完《代碼整潔之道》然后基于我7年寫代碼的經(jīng)驗所做總結(jié)凿蒜,以期能成為一個真正的好程序員禁谦。

java是有個@Auther注解~是的,作者废封,我們是代碼的作者州泊。我們要以作者心態(tài)自居,精心雕琢我們的代碼漂洋,以期讓我們的讀者在讀代碼時能賞心悅目遥皂。

如何能寫出好的代碼
好的代碼自己會說話-讓命名更有意義

程序中通常需要命名的有三種:方法、變量刽漂、類渴肉。其中變量又分為局部變量和成員變量。首先我們看下下面這個變量

int d  //過去的天數(shù);

是不是很懵逼爽冕,要知道這個d表示的什么意思仇祭,你要通讀這個變量的上下文才能知道。颈畸,即使你寫了注釋乌奇,當(dāng)你寫代碼時或讀代碼時是不是經(jīng)常要往上翻尋找這個d的注釋。如果你起一個有含義的變量名眯娱,那讀起來就大不一樣了礁苗,在代碼中直接就知道什么意思了。

 int elapsedTimeInDays;
 int daysSinceCreation;
 int daysSinceModification;
 int fileAgeInDays;

起上面這樣的變量名是不是好多了徙缴,在代碼中遇到直接就知道這個變量是什么意思试伙,甚至不用寫注釋也知道這個變量的意思,不用去翻看程序的上下文或者找這個變量的注釋于样。

再看下面的方法

public List<int[]> getThem() {
    List<int[]> list1 = new ArrayList<int[]>();
    for (int[] x : theList)
        if (x[0] == 4)
            list1.add(x);
    return list1;
}

看這樣的方法疏叨,你的頭頂是不是有很很多問號。倘若我們把方法名和變量名起的有意義一些呢如下:

public List<int[]> getFlaggedCells() {
    List<int[]> flaggedCells = new ArrayList<int[]>();
    for (int[] cell : gameBoard)
        if (cell[STATUS_VALUE] == FLAGGED)
            flaggedCells.add(cell);
    return flaggedCells;
}

這樣是不是好多了穿剖,僅僅把變量名改成的有意義寫蚤蔓,代碼就變得已讀了很多,此時還未改變代碼的結(jié)構(gòu)和嵌套糊余。如果更進(jìn)一步我們不用 int 數(shù)組表示單元格秀又,而是另寫一個類,這個類有個方法是否是Flagged的贬芥,遮掩住那個魔法變量則方法就能變成下面這樣吐辙。是不是更易讀了。

public List<Cell> getFlaggedCells() {
    List<Cell> flaggedCells = new ArrayList<Cell>();
    for (Cell cell : gameBoard)
        if (cell.isFlagged())
            flaggedCells.add(cell);
    return flaggedCells;
}

以上蘸劈,我們只是簡單了改變了代碼的名稱昏苏,代碼的易讀性大大提高。,代碼本身就是最好的注釋說明捷雕。

好的代碼自己會說話-準(zhǔn)確的命名椒丧、避免誤導(dǎo)

如果我們命名一個數(shù)組的話,那便不要使用accountList的命名救巷,這會給讀者誤導(dǎo)壶熏,誤以為這個變量是個List類型,所以用accountGroup或者arrayOfAccount甚至直接用accounts都會比accountList更好浦译。不準(zhǔn)確命名的另外一個經(jīng)常發(fā)生的例子是含有數(shù)字的變量名棒假,這種經(jīng)常發(fā)生我們要起一個變量名的時候發(fā)現(xiàn)這個變量重名了,我們經(jīng)常會再新變量后面加個數(shù)字來區(qū)分和原來的變量精盅。

public static void copyChars(char a1[], char a2[]) {
    for (int i = 0; i < a1.length; i++) {
        a2[i] = a1[i];
    }
}

上面的代碼如果改成下面的會不會好點

public static void copyChars(source  a1[], destination a2[]) {
    for (int i = 0; i < a1.length; i++) {
        destination[i] = source[i];
    }
}

命名還有一個經(jīng)常發(fā)生不準(zhǔn)確的命名的例子如下,這三個方法有什么區(qū)別呢帽哑,我們在使用時應(yīng)該用哪個呢?這種命名區(qū)分毫無意義叹俏,調(diào)用者照樣需要去看方法的實現(xiàn)或者注釋來決定使用哪個方法∑拚恚現(xiàn)代聰明的ide會把所有的方法列出來,然而你卻不知道該使用那個方法粘驰。

getActiveAccount();
getActiveAccounts();
getActiveAccountInfo();

消除魔法數(shù)字如下一段代碼屡谐,在代碼中直接使用數(shù)字,通常讀者不知道這個數(shù)字的含義蝌数,那當(dāng)別人來讀這段代碼的時候就要去找這個數(shù)字的含義

Order order = new Order();
order.setStatus(0);

這段代碼明顯是給訂單設(shè)置狀態(tài)愕掏。但是0是什么狀態(tài),如果沒有注釋或文檔的情況顶伞,需要找別的同事問呢饵撑,即使有注釋和文檔是不是也需要通過這段代碼的上下文去找0的含義呢。如果我們把訂單狀態(tài)定義成一個enum或者常量:

Orderd order= new Order();
order.setStatus(ORDER_STATUS_PAY);

改進(jìn)后的代碼是不是很明顯就知道這個地方把訂單的狀態(tài)設(shè)置為支付狀態(tài)了唆貌。

好的代碼自己會說話-類名和方法命名的更好實踐

如何才能讓我們的代碼命名更清晰簡短有效呢滑潘。下面是《代碼代碼簡潔之道》一書中做的總結(jié):

  • 類名應(yīng)該是名詞或名詞短語。如 Customer挠锥、WikiPage众羡、Account 和 AddressParser侨赡。避免使用 Manager蓖租、Processor、Data 或 Info 這樣的類名羊壹。類名不應(yīng)當(dāng)是動詞蓖宦。
  • 方法名應(yīng)當(dāng)是動詞或動詞短語,如 postPayment油猫、deletePage 或 save稠茂。屬性訪問器、修改器和斷言應(yīng)該根據(jù)其值命名,并依 Javabean 標(biāo)準(zhǔn)加上 get睬关、set 和 is 前綴诱担。
String name = employee.getName();
customer.setName("mike");
if (paycheck.isPosted())

重載構(gòu)造器時,使用描述了參數(shù)的靜態(tài)工廠方法名电爹。例如蔫仙,

Complex fulcrumPoint = Complex.FromRealNumber(23.0);

通常好于

Complex fulcrumPoint = new Complex(23.0);

因為FromRealNumber描述了這個構(gòu)造器和別的構(gòu)造器的不同之處。

  • 盡量給方法和類的命名都通俗易懂丐箩,不要為了耍寶起一些罕見的罕見的名字摇邦。畢竟代碼是用來讀的不是用來炫耀的。
  • 每種概念都對應(yīng)一個單詞屎勘,并且一以貫之施籍。如查詢方法經(jīng)常有g(shù)et、query概漱、find丑慎、select、fetch等詞我們最好選一個詞來對應(yīng)查詢這個概念
  • 盡量避免用含有多個意思的詞如add瓤摧,既可以表示加法立哑,又可以表示添加元素,有時會對讀程序的人產(chǎn)生誤導(dǎo)姻灶。
  • 使用某種解決方案領(lǐng)域的專有名稱铛绰,如果你使用了監(jiān)聽器,可以把類名后綴寫成listener产喉、如果使用訪問者模式捂掰,可以用visitor作為類的后綴,如果使用了門面模式可用face作為后綴曾沈,這樣在別的程序員讀你的代碼時就會有個全局的概念这嚣,知道你設(shè)計代碼時的思路。更好的理解代碼塞俱。
  • 如果不能使用計算機(jī)解決方案領(lǐng)域的名詞來命名姐帚,那就使用業(yè)務(wù)領(lǐng)域的名詞來命名吧。至少障涯,負(fù)責(zé)維護(hù)代碼的程序員就能去請教領(lǐng)域?qū)<伊耍?strong>優(yōu)秀的程序員和設(shè)計師罐旗,其工作之一就是分離解決方案領(lǐng)域和業(yè)務(wù)領(lǐng)域的概念。與所涉問題領(lǐng)域更為貼近的代碼唯蝶,應(yīng)當(dāng)采用源自業(yè)務(wù)領(lǐng)域的名稱九秀。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市粘我,隨后出現(xiàn)的幾起案子鼓蜒,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,000評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件都弹,死亡現(xiàn)場離奇詭異娇豫,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)畅厢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評論 3 399
  • 文/潘曉璐 我一進(jìn)店門锤躁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人或详,你說我怎么就攤上這事系羞。” “怎么了霸琴?”我有些...
    開封第一講書人閱讀 168,561評論 0 360
  • 文/不壞的土叔 我叫張陵椒振,是天一觀的道長。 經(jīng)常有香客問我梧乘,道長澎迎,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,782評論 1 298
  • 正文 為了忘掉前任选调,我火速辦了婚禮夹供,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘仁堪。我一直安慰自己哮洽,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,798評論 6 397
  • 文/花漫 我一把揭開白布弦聂。 她就那樣靜靜地躺著鸟辅,像睡著了一般。 火紅的嫁衣襯著肌膚如雪莺葫。 梳的紋絲不亂的頭發(fā)上匪凉,一...
    開封第一講書人閱讀 52,394評論 1 310
  • 那天,我揣著相機(jī)與錄音捺檬,去河邊找鬼再层。 笑死,一個胖子當(dāng)著我的面吹牛堡纬,可吹牛的內(nèi)容都是我干的聂受。 我是一名探鬼主播,決...
    沈念sama閱讀 40,952評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼隐轩,長吁一口氣:“原來是場噩夢啊……” “哼饺饭!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起职车,我...
    開封第一講書人閱讀 39,852評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后悴灵,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體扛芽,經(jīng)...
    沈念sama閱讀 46,409評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,483評論 3 341
  • 正文 我和宋清朗相戀三年积瞒,在試婚紗的時候發(fā)現(xiàn)自己被綠了川尖。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,615評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡茫孔,死狀恐怖叮喳,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情缰贝,我是刑警寧澤馍悟,帶...
    沈念sama閱讀 36,303評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站剩晴,受9級特大地震影響锣咒,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜赞弥,卻給世界環(huán)境...
    茶點故事閱讀 41,979評論 3 334
  • 文/蒙蒙 一毅整、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧绽左,春花似錦悼嫉、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至闯团,卻和暖如春辛臊,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背房交。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評論 1 272
  • 我被黑心中介騙來泰國打工彻舰, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人候味。 一個月前我還...
    沈念sama閱讀 49,041評論 3 377
  • 正文 我出身青樓刃唤,卻偏偏與公主長得像,于是被迫代替她去往敵國和親白群。 傳聞我的和親對象是個殘疾皇子尚胞,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,630評論 2 359