<ul id="qxxfc"><fieldset id="qxxfc"><tr id="qxxfc"></tr></fieldset></ul>


      為了獲得更好的閱讀體驗(yàn),請(qǐng)?jiān)L問(wèn)原文:傳送門(mén)
      <https://www.wmyskxz.com/2019/09/14/dai-ma-zheng-ji-zhi-dao-du-shu-bi-ji/>



      一、前言


      代碼是什么呢?或者說(shuō)作為程序員的我們,對(duì)于寫(xiě)代碼這件事又是抱著怎樣的一種態(tài)度呢?我時(shí)常都在想,如今我如愿成為了一名程序員(雖然還很菜),寫(xiě)代碼這件事成了我的工作,我期望從工作中獲得些什么?而工作又能給予我什么呢?

      我在短暫的工作經(jīng)歷中(4
      個(gè)月),犯下過(guò)不少錯(cuò),少部分是因?yàn)榻?jīng)驗(yàn),但大部分的情況下都是因?yàn)閷?duì)代碼沒(méi)有足夠的敬畏之心導(dǎo)致的,并且在工作中也遇到過(guò)一些很有意思的代碼,所以今天就著這本《代碼整潔之道》,來(lái)談一談對(duì)于代碼的感受和一些想法。(Ps:想吐槽一下這本書(shū)挺魔怔的..)

      二、什么是整潔的代碼

      我搜索「代碼」這兩個(gè)關(guān)鍵字,給出的官方解釋都特別有意思,摘一下百度百科的好了:

      代碼就是程序員用開(kāi)發(fā)工具
      <https://baike.baidu.com/item/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7/10464557>
      所支持的語(yǔ)言寫(xiě)出來(lái)的源文件 <https://baike.baidu.com/item/%E6%BA%90%E6%96%87%E4%BB%B6/6999107>
      ,是一組由字符 <https://baike.baidu.com/item/%E5%AD%97%E7%AC%A6/4768913>、符號(hào)或信號(hào)碼元
      <https://baike.baidu.com/item/%E7%A0%81%E5%85%83>
      以離散形式表示信息的明確的規(guī)則體系。代碼設(shè)計(jì)的原則包括唯一確定性、標(biāo)準(zhǔn)化和通用性、可擴(kuò)充性與穩(wěn)定性、便于識(shí)別與記憶、力求短小與格式統(tǒng)一以及容易修改等。?源代碼
      <https://baike.baidu.com/item/%E6%BA%90%E4%BB%A3%E7%A0%81/3814213>
      是代碼的分支,某種意義上來(lái)說(shuō),源代碼相當(dāng)于代碼。現(xiàn)代程序語(yǔ)言
      <https://baike.baidu.com/item/%E7%A8%8B%E5%BA%8F%E8%AF%AD%E8%A8%80/10696489>
      中,源代碼可以書(shū)籍或磁帶形式出現(xiàn),但最為常用格式是文本文件,這種典型格式的目的是為了編譯出計(jì)算機(jī)程序
      <https://baike.baidu.com/item/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%A8%8B%E5%BA%8F/3220205>
      。計(jì)算機(jī)源代碼最終目的是將人類可讀文本翻譯成為計(jì)算機(jī)可執(zhí)行的二進(jìn)制
      <https://baike.baidu.com/item/%E4%BA%8C%E8%BF%9B%E5%88%B6/361457>指令
      <https://baike.baidu.com/item/%E6%8C%87%E4%BB%A4/3225201>,這種過(guò)程叫編譯
      <https://baike.baidu.com/item/%E7%BC%96%E8%AF%91/1258343>,它由通過(guò)編譯器
      <https://baike.baidu.com/item/%E7%BC%96%E8%AF%91%E5%99%A8/8853067>完成。

      好了,學(xué)術(shù)介紹一大堆,重點(diǎn)還是在最后一句:計(jì)算機(jī)源代碼最終目的是將人類可讀文本翻譯成為計(jì)算機(jī)可執(zhí)行的二進(jìn)制指令。

      再精簡(jiǎn)一下:「人類可讀」、「計(jì)算機(jī)可執(zhí)行」。


      說(shuō)到底,代碼最終還是寫(xiě)給人看的,所以「可讀性」就顯得尤為重要,但總歸我們是要先有「代碼」,再有「可讀的代碼」,經(jīng)過(guò)不斷重構(gòu)or重寫(xiě),最終形成我們「簡(jiǎn)潔的代碼」。

      說(shuō)幾點(diǎn)感受比較大的吧。

      方法盡量短 && 職責(zé)單一

      有誰(shuí)能告訴我下面這個(gè)方法究竟是在做什么嗎?
      /** * @author Administrator * */ public class GeneratePrimes { /** * @param
      maxValue is the generation limit. * */ public static int[] generatePrimes(int
      maxValue) { if (maxValue >= 2){ //the only valid case //ddeclarations int s =
      maxValue +1 ;// size of array boolean[] f = new boolean[s]; int i; //initialize
      array to true. for ( i = 0;i < s;i++) { f[i] = true; } f[0] = f[1] = false; //
      sieve int j; for (i = 2;i < Math.sqrt(s) + 1; i++) { if (f[i]) { // if i is
      uncrossed , cross its multiples. for (j = 2 * i; j < s ;j += i) { f[j] = false;
      //multiple is not prime } } } // how many primes are there? int count = 0; for
      (i = 0;i < s; i++) { if (f[i]) { count ++; //bump count. } } int[] primes = new
      int[count]; //move the primes into the result for (i = 0,j = 0;i < s;i++) { if
      (f[i]) { primes[j++] = i; } } return primes; } else { //maxValue < 2 return new
      int[0]; // return null array if bad input. } } }
      如果你非常有耐心地看完了,你可能大概或許會(huì)了解到,這是一個(gè)返回 maxValue 范圍以內(nèi)的質(zhì)數(shù)的方法,但是我們經(jīng)過(guò)簡(jiǎn)單的重構(gòu)之后,會(huì)變得更加容易理解:
      public class PrimeGenerator { private static boolean[] crossedOut; private
      static int[] result; public static int[] generatePrimes(int maxValue) { if
      (maxValue < 2) { return new int[0]; } else { uncrossIntegersUpTo(maxValue);
      crossOutMultiples(); putUncrossedIntegersIntoResult(); return result; } }
      private static void putUncrossedIntegersIntoResult() { result = new
      int[numberOfUncrossedIntegers()]; for (int j = 0, i = 2; i < crossedOut.length;
      i++) { if (notCrossed(i)) { result[j++] = i; } } } private static int
      numberOfUncrossedIntegers() { int count = 0; for (int i = 2; i <
      crossedOut.length; i++) { if (notCrossed(i)) { count++; } } return count; }
      private static void crossOutMultiples() { int limit =
      determinuIterationLimit(); for (int i = 2;i <= limit; i++) { if (notCrossed(i))
      { crossOutMultiplesOf(i); } } } private static void crossOutMultiplesOf(int i)
      { for (int multiple = 2 * i; multiple < crossedOut.length; multiple +=i) {
      crossedOut[multiple] = true; } } private static boolean notCrossed(int i) {
      return crossedOut[i] == false; } private static int determinuIterationLimit() {
      double iterationLimit = Math.sqrt(crossedOut.length); return
      (int)iterationLimit; } private static void uncrossIntegersUpTo(int maxValue) {
      crossedOut = new boolean[maxValue+1]; for (int i = 2; i < crossedOut.length ;
      i++) { crossedOut[i] = false; } } }
      首先我們通過(guò)私有方法隱藏掉了實(shí)現(xiàn)的具體細(xì)節(jié),并且使用有意義的命名,使得我們主函數(shù) generatePrimes 更加便于理解。

      函數(shù)的第一規(guī)則就是要短小,第二條規(guī)則就是要更短小。每個(gè)函數(shù)保持職責(zé)單一,并且有意識(shí)的維持在一定行數(shù)內(nèi)(JVM 就強(qiáng)制要求每個(gè)函數(shù)要小于 8000
      行...也聽(tīng)過(guò)每個(gè)函數(shù)盡量維持在 15 行 or 30 行
      之內(nèi)這樣的說(shuō)法..可能有點(diǎn)魔怔,但要點(diǎn)就是函數(shù)要盡量短?。?,這當(dāng)然是最理想的情況,而現(xiàn)實(shí)的情況往往要糟糕一些。


      在工作中,我就遇到過(guò)一些長(zhǎng)得可怕的方法,他們或許本來(lái)保持著單純,職責(zé)單一,但是經(jīng)過(guò)業(yè)務(wù)不斷的改造,需求不斷的疊加,甚至是一些臨時(shí)邏輯的加入,這個(gè)方法就變得越來(lái)越臃腫不堪...并且因?yàn)闃I(yè)務(wù)的不斷發(fā)展,越來(lái)越少的人會(huì)
      care 到它,以至于改造成本越來(lái)越大,甚至被遺忘在角落..

      這其實(shí)是再正常不過(guò)的事情,但在多人協(xié)作的項(xiàng)目中,有一點(diǎn)需要自己來(lái)維持清醒,那就是:「一個(gè)方法就可以返回的為什么要寫(xiě)兩個(gè)?」
      ,關(guān)于這一點(diǎn),保持自己的思考就好了..

      注釋要體現(xiàn)代碼之外的東西


      有一句聽(tīng)起來(lái)好厲害的話叫做:「代碼即注釋」,不知道大家是怎么看待這樣一句話的,或者說(shuō)是怎么看待注釋的。其實(shí)反過(guò)來(lái)想,如果你的代碼需要大量的注釋來(lái)解釋其中的邏輯,會(huì)不會(huì)是代碼本身就存在一定問(wèn)題?或者換個(gè)角度思考,注釋是用來(lái)解釋代碼邏輯的嗎?

      可怕的廢話

      我們來(lái)看下面這一段代碼的注釋:
      /** The name. */ private String name; /** The version. */ private String
      version; /** The licenceName. */ private String licenceName; /** The version.
      */ private String info;
      上面這些 Javadoc
      的目的是什么?答案是:無(wú)。并且仔細(xì)閱讀,你甚至?xí)l(fā)現(xiàn)一處剪切-粘貼導(dǎo)致的錯(cuò)誤,如果作者在寫(xiě)(或粘貼)注釋時(shí)都沒(méi)有花心思,怎么能指望讀者從中收益呢?

      能用函數(shù)或變量時(shí)就別用注釋

      看看以下代碼概要:
      // does the module from the globale list <mod> depend on the // subsystem we
      are part of? if
      (smodule.getDependSubsystems().contains(subSysMod.getSubSystem())
      可以修改成以下沒(méi)有注釋的版本:
      ArrayList moduleDependes = smodule.getDependSubsystems(); String ourSubSystem
      = subSysMod.getSubSystem(); if (moduleDependes.contains(ourSubSystem))
      用代碼來(lái)闡述

      有時(shí),代碼本身不足以解釋其行為。但不幸的是,許多程序員以此為由,覺(jué)得大部分時(shí)候代碼都不足以解釋工作。這種觀點(diǎn)純屬錯(cuò)誤,比如你愿意看到下面這個(gè):
      // Check to see if the employee is eligible for full benefits if
      ((employee.flags & HOURLY_FLAG) && (employee.age > 65))
      還是這個(gè):
      if (employee.isEligibleForFullBenefits())
      只需要多思考那么幾秒鐘,就能用代碼解釋你的大部分意圖。其實(shí)很多時(shí)候,簡(jiǎn)單到只需要?jiǎng)?chuàng)建一個(gè)描述與注釋所言同一事物的函數(shù)即可。

      小結(jié)

      注釋終歸是要用來(lái)體現(xiàn)代碼之外的東西..

      名副其實(shí)的名字

      取名字這件事,真的是程序員的一門(mén)藝術(shù)。腦海里面能浮現(xiàn)出同事們用翻譯軟件取名的畫(huà)面嗎?

      一個(gè)好的名字再怎么夸贊都不為過(guò),但是這個(gè)最基礎(chǔ)的前提就是,它首先得是一個(gè)「正確的名字」。我就遇到過(guò)一次,函數(shù)名字叫做類似于 listAll
      這樣的東西,戳進(jìn)去看實(shí)際上還基于業(yè)務(wù)規(guī)則做了過(guò)濾..(這樣的牛肉不對(duì)馬嘴的情況又讓我聯(lián)想到了注釋這樣的東西,可能實(shí)際的代碼已經(jīng)作了更改,但是注釋還是是維持原樣沒(méi)有變化..)

      并且還有一個(gè)特別有意思的點(diǎn),就是關(guān)于名字的「長(zhǎng)度」。有時(shí)候可能為了想要描述清楚一個(gè)變量 or
      一個(gè)類的具體作用,我會(huì)給它起一個(gè)看起來(lái)特別長(zhǎng)的名字..關(guān)于這個(gè),這里有一些小經(jīng)驗(yàn)可以分享一下:

      * 去掉 Info 和 Data 這樣的后綴:這些就像是英語(yǔ)中的 a/ an/ the 一樣,是意義含糊的廢話,廢話都是冗余的..
      * 不要給變量加前綴來(lái)標(biāo)識(shí):變量不需要一個(gè) m_ or 其他什么的前綴來(lái)標(biāo)識(shí)這是一個(gè)變量..
      * 思考是否有必要標(biāo)識(shí)出變量的類型:我們標(biāo)注出變量的類型的目的是什么?對(duì)于弱類型的語(yǔ)言,可能有時(shí)候還是必要的,因?yàn)槲覀冇袝r(shí)候并不能從 students
      這個(gè)變量中判明我應(yīng)該怎樣對(duì)這個(gè)變量進(jìn)行操作,但是對(duì)于 Java 這樣的強(qiáng)類型的語(yǔ)言,我們就需要根據(jù)實(shí)際的場(chǎng)景思考是否真有那么必要了。
      無(wú)副作用

      函數(shù)承諾只做一件事,但還是會(huì)做其他被隱藏起來(lái)的事。
      public class UserValidator { private Cryptographer cryptographer; public
      boolean checkPassword(String userName, String password) { User user =
      UserGateway.findByName(userName); if (user != User.NULL) { String codedPhrase =
      user.getPhraseEncodedByPassrod(); String phrase =
      cryptographer.decrypt(codedPhrase, password); if ("Vliad
      Passwordw".equals(phrase)) { Session.initialize(); return true; } } return
      false; } }
      上面的函數(shù)副作用就在于對(duì) Session.initialize() 的調(diào)用。checkPassword
      函數(shù),顧名思義就是用來(lái)檢查密碼的,該名稱并未暗示它會(huì)初始化該次會(huì)話。所以,當(dāng)某個(gè)誤信了函數(shù)名的調(diào)用者想要檢查用戶有效性時(shí),就得冒著抹除現(xiàn)有會(huì)話數(shù)據(jù)的風(fēng)險(xiǎn)。

      所以這里可以重命名函數(shù)為 checkPasswordAndInitializeSession,雖然這還是違背了 "只做一件事" 的規(guī)則。

      函數(shù)參數(shù)盡可能少

      一個(gè)函數(shù)最理想的參數(shù)數(shù)量是 0,其次是 1,再次是 2.. 要避免使用三個(gè)以上參數(shù)的情況,因?yàn)閰?shù)帶有太多的概念性,參數(shù)過(guò)多就會(huì)帶來(lái)更多的復(fù)雜性..

      我就見(jiàn)過(guò)一個(gè)查詢接口,為了滿足不同的復(fù)雜查詢場(chǎng)景,參數(shù)大概可能有接近 10 個(gè).. 就算不為接手的編碼人員考慮,測(cè)試人員也會(huì)頭疼的..
      想想看,要覆蓋如此兼容如此多場(chǎng)景如此復(fù)雜的一個(gè)查詢接口,測(cè)試用例究竟應(yīng)該怎么寫(xiě)呢?

      More..

      這本書(shū)說(shuō)實(shí)話看下來(lái)挺魔怔的.. 里面有許多簡(jiǎn)潔實(shí)用的觀點(diǎn)可以讓我們受益,我僅僅挑了一些最近比較感同身受的幾點(diǎn),來(lái)進(jìn)行了說(shuō)明。


      代碼倉(cāng)庫(kù)就像是一本《哈姆雷特》一樣,每個(gè)人都有自己不同的見(jiàn)解,這無(wú)可厚非,我覺(jué)得重要的就是要保持對(duì)代碼的敬畏之心,保持自身的思考,才能讓我們不斷向前(說(shuō)話都變魔怔了..)

      三、代碼之外

      每個(gè)人都能寫(xiě)出好的代碼

      這就是一個(gè)非常有意思的話題了,我們可以分成幾個(gè)角度來(lái)思考:

      * 好的代碼是寫(xiě)出來(lái)的嗎?(這可能有點(diǎn)類似于好的文章是寫(xiě)出來(lái)的嗎?)
      * 為什么我們寫(xiě)不出好的代碼?
      我記得之前在看《重構(gòu):改善既有代碼的設(shè)計(jì)》
      <https://www.wmyskxz.com/2019/06/08/chong-gou-gai-shan-ji-you-dai-ma-de-she-ji-du-shu-bi-ji/>
      這本老經(jīng)典的書(shū)的時(shí)候,就提到一種觀點(diǎn)說(shuō):「重構(gòu)不是一個(gè)一蹴而就的事,需要長(zhǎng)期的實(shí)踐和經(jīng)驗(yàn)才能夠完成得很好。重構(gòu)強(qiáng)調(diào)的是 Be
      Better,那在此之前我們首先需要先動(dòng)起手來(lái)搭建我們的系統(tǒng),而不要一味地“完美主義”?!?br>
      好的代碼也是這樣,需要一個(gè)循序漸進(jìn)的過(guò)程,雖然大部分時(shí)候,經(jīng)驗(yàn)可以讓我們少走許多彎路,但這些都是一個(gè)過(guò)程。

      當(dāng)然上面所說(shuō)的全部,都是理想中的狀況,而現(xiàn)實(shí)中的情況往往不允許我們這樣做。什么之前炒起來(lái)的 996,什么
      ICU,都無(wú)情的揭示著大部分程序員的現(xiàn)狀:忙。忙于各種已經(jīng)堆成山的需求 && 修復(fù)各種 BUG 中。

      我學(xué)到一個(gè)很正經(jīng)的概念,叫做「管窺」,附帶的一種概念叫做「稀缺」。(看完下面這個(gè)故事應(yīng)該很容易理解,故這里不作解釋..)


      我記得之前看過(guò)一篇報(bào)道,說(shuō)是香港某富豪在節(jié)目中要體驗(yàn)幾天環(huán)衛(wèi)工人,參加節(jié)目前,他曾說(shuō)過(guò):“我的人生其實(shí)沒(méi)有很多時(shí)間坐下來(lái),想想現(xiàn)在的生活不錯(cuò),享受一下。我有時(shí)間就會(huì)計(jì)劃下一步!"



      可幾天下來(lái),讓他最糾結(jié)的竟然是吃飯問(wèn)題,他對(duì)著鏡頭說(shuō):“很奇怪,我這兩天只是考慮吃東西,完全沒(méi)什么盼望,什么都不想。我努力工作,就是希望吃一頓好的。”

      程序員是一種很容易陷入,對(duì)于時(shí)間「稀缺」?fàn)顟B(tài)的物種。
      稀缺會(huì)俘獲我們的注意力,并帶來(lái)一點(diǎn)點(diǎn)好處:我們能夠在應(yīng)對(duì)迫切需求時(shí),做得更好。但從長(zhǎng)遠(yuǎn)的角度來(lái)看,我們的損失更大:我們會(huì)忽視其他需要關(guān)注的事項(xiàng),在生活的其他方面變得不那么有成效。(摘自《稀缺》P17)


      這聽(tīng)上去就像是在找借口一樣,但其實(shí)有點(diǎn)差別。我發(fā)覺(jué)每個(gè)人其實(shí)都能夠?qū)懗龊玫拇a,只是取決于你有沒(méi)有這樣的意識(shí),有沒(méi)有堅(jiān)持自己的思考,更重要的是,有沒(méi)有「跳出需求」,甚至是「跳出工作」之外來(lái)思考,就像是要跳出「我們明明知道了很多道理,卻依然過(guò)不好這一生」的怪圈一樣。

      結(jié)尾

      這一段時(shí)間都不怎么更新了,不是我變懶了.. 前段時(shí)間就陷入了不加班就完成不了工作的狀態(tài),一方面是因?yàn)槭虑楸容^雜.. 另外一方面就是自己效率還不夠高..
      (悄悄說(shuō):雖然很忙,但是總是能抽得出時(shí)間玩兒手機(jī) hhhh...)值得反思吧.. 最近也開(kāi)始有一些覺(jué)得越來(lái)越難下筆了.. 想寫(xiě)的東西很多,但總怕寫(xiě)不好..


      另外,程序員真的是很有意思的職位了,并且也覺(jué)得程序員都多少帶著點(diǎn)兒自己的驕傲來(lái)得,因?yàn)槊刻於荚谧约旱氖澜缤鎯浩磮D,自己就是世界的造物主,久了,難免有些受影響..(主要體現(xiàn)在溝通上..)

      摁.. 總之這是一本很好的書(shū),建議感興趣的童鞋可以溜一遍。

      按照慣例黏一個(gè)尾巴:

      歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)注明出處!
      獨(dú)立域名博客:wmyskxz.com
      簡(jiǎn)書(shū)ID:@我沒(méi)有三顆心臟 <https://www.jianshu.com/u/a40d61a49221>
      github:wmyskxz <https://github.com/wmyskxz/>
      歡迎關(guān)注公眾微信號(hào):wmyskxz
      分享自己的學(xué)習(xí) & 學(xué)習(xí)資料 & 生活
      想要交流的朋友也可以加qq群:3382693
      錢(qián)

      友情鏈接
      ioDraw流程圖
      API參考文檔
      OK工具箱
      云服務(wù)器優(yōu)惠
      阿里云優(yōu)惠券
      騰訊云優(yōu)惠券
      京東云優(yōu)惠券
      站點(diǎn)信息
      問(wèn)題反饋
      郵箱:[email protected]
      QQ群:637538335
      關(guān)注微信

        <ul id="qxxfc"><fieldset id="qxxfc"><tr id="qxxfc"></tr></fieldset></ul>
          羽月希奶水饱胀在线播放 | 欧美日韩国产伦理 | 日韩av导航| 亚洲A片在线观看 | 韩国精品国产 | 国产三级午夜理伦三级的结局 | 韩国makemodel44人体 | 男男视频免费观看网站国产 | 午夜精品久久久久久久免费APP | 国产露脸150部国语对白 |