編程中思考

前言

前不久在微博上關(guān)注一個(gè)ID為的微博用戶(后來百科之后才發(fā)現(xiàn)又是國內(nèi)程序員中的牛人之一铐达,就是池大大文章經(jīng)常提到的“王垠”),無意間查看了他之前發(fā)的微博,其中許多都是對一些編程語言的犀利評價(jià),而所發(fā)的微博之中一篇名為編程的智慧長文吸引了我注意巧还,出于對內(nèi)容的好奇就對這篇文章進(jìn)行了閱讀鞭莽。閱讀過程中,發(fā)現(xiàn)了博主對編程和設(shè)計(jì)語言的思考都有著獨(dú)立深刻的見解澎怒,文章里都是對如何在編程中成長和對代碼正確實(shí)踐的干貨指導(dǎo),旨在幫助那些把編程作為主職工作的人們在技術(shù)開發(fā)的路上更好地找到屬于自己正確的方向阶牍。閱讀完這篇文章后喷面,我發(fā)現(xiàn)里面提到的條條編程規(guī)范和編碼要求星瘾,對自己現(xiàn)在以及未來的編程之路都有著很大的價(jià)值,也讓我設(shè)想如何編程中更好融入自己的思考惧辈,對代碼的反思以及對程序設(shè)計(jì)的反思琳状。
在閱讀了文章后幾天,自己也不時(shí)地想如何在編程中有效成長盒齿,覺得有必要將文章《編程的智慧》中對針對自己有價(jià)值的內(nèi)容提取記錄下來念逞,進(jìn)行自我針對性的思考和實(shí)踐,于是也就有了寫這篇文章念頭县昂。

內(nèi)容

編程提高 - 代碼提煉

文中提到提高編程水平最有效的方法——提煉代碼肮柜,學(xué)會對自己所寫的代碼進(jìn)行思考。當(dāng)寫完一段代碼看看是不是太長了倒彰,還能夠縮減嗎审洞?是不是可讀性太差了,要靠不必要的注釋讓其它人甚至以后的自己才能看懂這段代碼待讳。用這樣的思考過程來提煉自己的代碼芒澜,減少代碼中的冗余。就算是閱讀開源庫或者一些其它人的代碼時(shí)创淡,也應(yīng)該用這樣思考方式來閱讀他們的代碼痴晦,來提取他人代碼中的精華。這里引用下文章里一句話"作為一個(gè)好的程序員琳彩,應(yīng)該看他刪掉過自己多少的代碼誊酌,留下來又是怎樣的代碼。"只有對自己的代碼進(jìn)行反復(fù)地思考露乏,修改和提煉碧浊,以此才能改進(jìn)自己的代碼質(zhì)量,真正提高自己的編程水平瘟仿。

優(yōu)雅的代碼 - 讓代碼更加清晰

優(yōu)雅的代碼應(yīng)該是容易管理和查看的箱锐,并且邏輯結(jié)構(gòu)上是應(yīng)該對稱的,就像樹叉式的樹
狀結(jié)構(gòu)劳较,一個(gè)常見的場景就是在if/else語句的使用上驹止,讓if/else的分支永遠(yuǎn)都是成對出現(xiàn),不要僅僅因?yàn)槭÷缘羯倭康闹貜?fù)性代碼而去省略一個(gè)else的分支观蜗,這樣一來破壞整個(gè)邏輯的結(jié)構(gòu)和對稱性臊恋,使得在代碼理解上就需要多一點(diǎn)投入。

if (conditionA) {
  ...
  if (conditionA-1) {
      ...
  } else {
      ...
  }
  ...
} else if (conditionB) {
  ...
} else {
  ...
}

模塊化的代碼 - 讓代碼更加獨(dú)立

對代碼的模塊化墓捻,應(yīng)該是對代碼所表示的邏輯進(jìn)行模塊化捞镰,也可以在單個(gè)文件進(jìn)行模塊化的抽取,而不是單純地將代碼分成多個(gè)不同的文件和目錄。對代碼進(jìn)行模塊化處理的一種常見且比較有效就是"使用函數(shù)"岸售,通常的函數(shù)都會有一個(gè)輸入和對應(yīng)的輸出,因此就可以將能夠模塊化的代碼用不同的函數(shù)進(jìn)行各自的封裝厂画,在最后的使用就是對模塊化函數(shù)的組合調(diào)用凸丸。

文章也提到了想讓代碼更好模塊化的必要方式:

  • 避免使用過長的函數(shù)。針對存在的過長的函數(shù)袱院,就要想方設(shè)法地去拆分成更小的函數(shù)屎慢,進(jìn)行整合調(diào)用。在函數(shù)長度的控制上忽洛,最好保持在40~50行以內(nèi)一個(gè)函數(shù)腻惠。
  • 使用小的工具函數(shù)。針對一些雖然結(jié)構(gòu)簡單(可能只是一個(gè)倆三行代碼的真假判斷)但仍然會重復(fù)使用的代碼提取成小的函數(shù)欲虚,來簡化主要函數(shù)的邏輯集灌。
  • 保持函數(shù)的單一性原則。避免寫出通用的复哆,用來表示可以做這個(gè)又可以做那個(gè)的函數(shù)欣喧,讓每個(gè)函數(shù)盡量只做一件簡單的事情。當(dāng)兩段代碼的共同點(diǎn)少于它們的不同點(diǎn)時(shí)就應(yīng)該將連兩段代碼分別放在不同函數(shù)中梯找,可以將其中相同的部分單獨(dú)抽取成另外一個(gè)函數(shù)來調(diào)用唆阿。
  • 減少和避免全局變量和類變量的使用。將全局變量或者類變量作為類里不同函數(shù)間的共享數(shù)據(jù)锈锤,成為函數(shù)間的數(shù)據(jù)通道驯鳖。一方面,這樣一來破壞函數(shù)間模塊化的結(jié)構(gòu)久免,無法做到讓函數(shù)離開類而存在浅辙;另一方面,這個(gè)變量還很可能在其它地方進(jìn)行修改妄壶,這樣讓代碼理解上更加復(fù)雜和容易出錯(cuò)摔握。

可讀的代碼 - 恰當(dāng)?shù)孛〖模瑴p少注釋

文章主張了"真正優(yōu)雅可讀的代碼,是幾乎不需要注釋的"伊磺,當(dāng)然這樣的說法也是需要前提的。而給代碼寫注釋這件事上屑埋,在方便他人的閱讀上的確有所作用豪筝,而大量注釋存在于代碼之中续崖,讓代碼本身閱讀起來更加困難,并且隨著代碼不斷改進(jìn)和更新严望,也帶來了更新注釋的成本多艇。當(dāng)然注釋也有存在的必要性像吻,在少數(shù)的情況下峻黍,使用違反常規(guī)做法的代碼實(shí)現(xiàn)則需要使用短注釋來解釋說明設(shè)計(jì)實(shí)現(xiàn)的理由。

以下就是幾個(gè)文章提到減少寫注釋的必要方法:

  • 使用有意義的函數(shù)和變量名拨匆。讓函數(shù)和變量名字能夠具體地描述它們的邏輯和用途姆涩。
  • 局部變量的聲明和它被函數(shù)使用的位置盡量接近。減少一開始就聲明大量局部變量惭每,卻在很遠(yuǎn)處才使用這些局部變量的做法骨饿,這樣會讓原本的代碼執(zhí)行路徑更加復(fù)雜,還會出現(xiàn)在中間過程中被修改卻不易察覺的問題洪鸭。

"局部變量的本質(zhì)——作為電路中導(dǎo)線的存在"

  • 局部變量名盡量簡短样刷。雖然變量名被縮簡,但結(jié)合有意義的代碼執(zhí)行的上下文览爵,要讓讀者輕易地理解局部變量的含義置鼻。
  • 減少局部變量的重用。避免對局部變量進(jìn)行聲明后進(jìn)行反復(fù)使用,不應(yīng)該為了簡單地重用變量而擴(kuò)大變量的作用域,防止在其他地方被使用.
if (...) {
  let info = "good"
  print(info)
} else {
  let info = "bad"
  print(info)
}
  • 將復(fù)雜的邏輯提取成"幫助函數(shù)".在一個(gè)很長的函數(shù)中,對于存在的不清晰的代碼片段往往可以提取出來,做成一個(gè)函數(shù),然后在原來的地方進(jìn)行調(diào)用,而將函數(shù)命名為更有意義,以此來代替原本所要添加的注釋.
  • 將復(fù)雜的表達(dá)式提取出來,用中間變量表示.控制單行代碼的長度,使用中間變量來防止代碼過度嵌套所造成的理解困難.
  • 在合理的地方換行.不要單純地依靠IDE的自動(dòng)換行功能,應(yīng)該根據(jù)代碼的邏輯來進(jìn)行換行,這樣容易幫助理解代碼.

簡單的代碼 - 使用程序語言中經(jīng)過時(shí)間考驗(yàn)的特性

每一個(gè)程序語言多少會有一些自己的語言特性,對于語言特性的使用,應(yīng)以其可靠,有效的前提下使用,并非語言提供什么特性蜓竹,就一定需要用到什么.

幾個(gè)具體的應(yīng)該避免使用的語言特性如下:

  • 避免使用自增自減表達(dá)式.表達(dá)式將讀寫不同的操作混合在了一起,讓語義更加?混亂,使用i+=1/i-=1進(jìn)行代替.
  • 不要去省略花括號.不要因?yàn)檎Z言特性支持if-else的括號省略而單單利用縮進(jìn),極易出現(xiàn)如下錯(cuò)誤:
if (...)
    action1()
    action2()

原本if條件下只有執(zhí)行action1函數(shù),而意外地對action2進(jìn)行縮進(jìn),使得也作為if條件下執(zhí)行函數(shù)而等待調(diào)用.

  • 合理使用括號.在比較復(fù)雜的操作符表達(dá)式中,不要盲目利用操作符的優(yōu)先級, 必要地使用括號讓表達(dá)式閱讀起來更加容易理解.
  • 避免使用break和continue. 在循環(huán)語句中使用了break或者continue就會讓循環(huán)的邏輯和終止條件變得復(fù)雜,難以保證其條件的正確性.而出現(xiàn)的break或者continue往往可以通過調(diào)整循環(huán)的邏輯來解決,這時(shí)候就應(yīng)該重新思考循環(huán)的邏輯箕母,重新設(shè)計(jì)。比如:
    • 出現(xiàn)continue,嘗試將continue的條件反向,以此消除continue
/*
  for(...) {
      if(conditon1) {
          continue;
      }
      ...
  } 
*/
  for(...) {
      if (!condition1) {
          ...
      }
  }
  • 出現(xiàn)break, 嘗試將break的條件放置于循環(huán)的終止條件中.
/*
while (condition1) {
    ...
    if (condition2) {
        break;
    }
}
*/
while (condition1 & !condition2) {
...  
}
  • 有時(shí)break可以被return代替,而循環(huán)中使用return是沒有問題.
  • 將循環(huán)中復(fù)雜的實(shí)現(xiàn)部分提取出來,作為函數(shù)去調(diào)用,然后再去嘗試處理消除break/continue.

直觀的代碼 - 永遠(yuǎn)用更直接,更清晰的寫法

表達(dá)復(fù)雜的執(zhí)行條件判斷時(shí),減少邏輯運(yùn)算符的使用,利用簡單的if-else嵌套,可以讓函數(shù)執(zhí)行條件更加清晰.

正確處理錯(cuò)誤

  • 對錯(cuò)誤異常的catch,必須做出合理的處理,而不是選擇忽略掉.
  • catch到的異常應(yīng)該明確異常的類型和對應(yīng)信息,不要將其作為寬泛的Exception類型來處理.
  • 對可能出現(xiàn)異常的函數(shù)需要throw時(shí),盡量避免多層次的異常傳遞,應(yīng)該在異常出現(xiàn)的當(dāng)時(shí)就進(jìn)行處理.
  • try-catch的代碼應(yīng)該盡可能地少,使得調(diào)試更加容易.

正確處理null指針

null其實(shí)不是一個(gè)合法的對象,類型應(yīng)該是NULL,不該是任何其他一種普通類型.而充分利用窮舉法的思想,去更好處理null指針:

  • 函數(shù)盡量不要返回null.針對需要返回"沒有"的函數(shù),允許使用"null" 表示沒有;而對于返回"錯(cuò)誤"的函數(shù),應(yīng)該使用拋異常應(yīng)對,而不是返回null值,"沒有"與"出錯(cuò)"是完全不同的概念.
  • 不要去catch null相關(guān)的異常.針對可能存在null值的情況必須進(jìn)行null檢查.
  • 不要將null放進(jìn)"容器數(shù)據(jù)結(jié)構(gòu)".在一些集合如Array,List,Set,Map等中加入null,會由于容器的動(dòng)態(tài)性變化更加難以控制,使得取值時(shí)必須進(jìn)行null檢查,讓調(diào)試也更加困難,而對應(yīng)的解決方案:可以用一個(gè)特殊,合法的對象來表示集合容器中的"沒有".
  • 函數(shù)調(diào)用時(shí)對null盡早處理.明確null表示的意義,盡早地檢查和處理null值,必須減少它的傳播.
  • 函數(shù)設(shè)計(jì)時(shí)明確聲明不接受null參數(shù).不要對null值進(jìn)行容錯(cuò)處理,針對null值的輸入應(yīng)該終止程序的繼續(xù).面對null?值,最正確的做法就是最強(qiáng)硬的做法俱济。
  • 使用Optional類型.null指針問題的存在,是由于其允許在沒有檢查null的情況下進(jìn)行訪問;而Optional則將檢查和訪問操作進(jìn)行合二為一,這樣一來使得值被使用時(shí)必須先檢查.

防止過渡工程和過渡設(shè)計(jì)

  • 先把眼前的問題解決掉,解決好,再去考慮以后的擴(kuò)展問題.
  • 先寫出可用的代碼,再進(jìn)行推敲和改進(jìn),考慮重用的問題.
  • 先寫出有效, 簡單, 沒有明顯Bug的代碼, 再考慮測試的問題.

總結(jié)

面對長長一篇的干貨文章嘶是,自己粗淺的總結(jié)下來也需要不少文字,更何況里面有著許多的內(nèi)容需要反復(fù)的推敲和琢磨,也有著不少內(nèi)容需要大量的實(shí)踐和思考后才會有更深一步理解,.而每一段時(shí)間的實(shí)踐和思考想必讓這篇文章帶來的價(jià)值不斷彰顯,的確值得在不同時(shí)期都多看幾遍,一定要多回顧蛛碌。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末聂喇,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子蔚携,更是在濱河造成了極大的恐慌希太,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件酝蜒,死亡現(xiàn)場離奇詭異誊辉,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)亡脑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進(jìn)店門堕澄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來邀跃,“玉大人,你說我怎么就攤上這事蛙紫∨男迹” “怎么了?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵惊来,是天一觀的道長丽涩。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么继准? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任移必,我火速辦了婚禮,結(jié)果婚禮上秒赤,老公的妹妹穿的比我還像新娘憎瘸。我一直安慰自己,他們只是感情好潮售,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布酥诽。 她就那樣靜靜地躺著肮帐,像睡著了一般边器。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上肮砾,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天仗处,我揣著相機(jī)與錄音,去河邊找鬼婆誓。 笑死,一個(gè)胖子當(dāng)著我的面吹牛郁轻,可吹牛的內(nèi)容都是我干的文留。 我是一名探鬼主播,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼骑篙,長吁一口氣:“原來是場噩夢啊……” “哼靶端!你這毒婦竟也來了凛膏?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤台谍,失蹤者是張志新(化名)和其女友劉穎典唇,沒想到半個(gè)月后胯府,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡炎咖,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年乘盼,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了绸栅。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片页屠。...
    茶點(diǎn)故事閱讀 38,059評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蓖柔,死狀恐怖况鸣,靈堂內(nèi)的尸體忽然破棺而出竹观,到底是詐尸還是另有隱情,我是刑警寧澤懂酱,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布玩焰,位于F島的核電站芍锚,受9級特大地震影響蔓榄,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜逃魄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一伍俘、第九天 我趴在偏房一處隱蔽的房頂上張望勉躺。 院中可真熱鬧,春花似錦妨退、人聲如沸蜕企。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽唇牧。三九已至聚唐,卻和暖如春拱层,著一層夾襖步出監(jiān)牢的瞬間宴咧,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工烙肺, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留氧卧,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓搏明,卻偏偏與公主長得像闪檬,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子虚循,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 通過這本書茎刚,我們可以開始理解數(shù)據(jù)可視化炕檩,探索數(shù)據(jù)的模式,并尋找數(shù)據(jù)間的關(guān)聯(lián)笛质,進(jìn)而選擇適合自己的數(shù)據(jù)和目的的可視化方...
    踏雁尋花閱讀 1,993評論 1 2
  • 水果觀念 中國營養(yǎng)協(xié)會建議一個(gè)人一天攝入250g到300g的水果妇押,大概兩個(gè)拳頭的量。眾多水果中敲霍,榴蓮丁存、鮮棗柴我、香蕉含...
    亦亦大閱讀 235評論 0 0
  • 愛情是燈界睁,友情是影子,當(dāng)燈滅了逾礁,你會發(fā)現(xiàn)你的周圍都是影子。朋友嘹履,是在最后可以給你力量的人。 ——電影《當(dāng)...
    燕子的留聲館閱讀 289評論 0 2
  • 一切速成都是耍流氓植捎,捷徑就是最長的彎路。
    禾顏越瑟閱讀 156評論 0 1