代碼優化基本原則

代碼優化基本原則

  1. 易讀性優先
  2. 如果不是性能瓶頸,就不要爲了性能而改寫代碼
  3. 複雜性守恆原則:無論你怎麼寫代碼,複雜性都是不會消失的
    推論:如果邏輯很複雜,那麼代碼看起來就應該是複雜的。如果邏輯很簡單,代碼看起來就應該是簡單的。

命名

程序員三大難題

  1. 變量命名
  2. 緩存失效
  3. 循環邊界

可見變量命名的重要性。

網上有很多命名規範,大家可以參考。這裏只講基本原則。

  1. 注意詞性

    • 普通變量/屬性用「名詞」

        var person = {
            name: 'Frank'
        }
        var student = {
            grade: 3,
            class: 2
        }
      
      
    • bool變量/屬性用「形容詞」或者「be動詞」或者「情態動詞」或者「hasX」

        var person = {
            dead: false, // 如果是形容詞,前面就沒必要加 is,比如isDead 就很廢話
            canSpeak: true, //情態動詞有 can、should、will、need 等,情態動詞後面接動詞
            isVip: true, // be 動詞有 is、was 等,後面一般接名詞
            hasChildren: true, // has 加名詞
        }
      
      
    • 普通函數/方法用「動詞」開頭

        var person = {
            run(){}, // 不及物動詞
            drinkWater(){}, // 及物動詞
            eat(foo){}, // 及物動詞加參數(參數是名詞)
        }
      
      
    • 回調、鉤子函數用「介詞」開頭,或用「動詞的現在完成時態」

        var person = {
            beforeDie(){},
            afterDie(){},
            // 或者
            willDie(){}
            dead(){} // 這裏跟 bool 衝突,你只要不同時暴露 bool dead 和函數 dead 就行,怕衝突就用上面的 afterDie
        }
        button.addEventListener('click', onButtonClick)
        var component = {
            beforeCreate(){},
            created(){},
            beforeMount(){},
            mounted(){},
            beforeUpdate(){},
            updated(){},
            activated(){},
            deactivated(){},
            beforeDestroy(){},
            destroyed(){},
            errorCaptured(){}
        }
      
      
    • 容易混淆的地方加前綴

        div1.classList.add('active') // DOM 對象
        div2.addClass('active') // jQuery 對象
        不如改成
        domDiv1 或 elDiv1.classList.add('active')
        $div2.addClass('active')
      
      
    • 屬性訪問器函數可以用名詞

        $div.text() // 其實是 $div.getText()
        $div.text('hi') // 其實是 $div.setText('hi')
      
      
  2. 注意一致性

    • 介詞一致性
      如果你使用了 before + after,那麼就在代碼的所有地方都堅持使用
      如果你使用了 before + 完成時,那麼就堅持使用
      如果你改來改去,就「不一致」了,不一致將導致「不可預測」

    • 順序一致性
      比如 updateContainerWidth 和 updateHeightOfContainer 的順序就令人很彆扭,同樣會引發「不可預測」

    • 表裏一致性
      函數名必須完美體現函數的功能,既不能多也不能少。
      比如

        function getSongs(){
            return $.get('/songs).then((response){
                div.innerText = response.songs
            })
        }
      
      

      就違背了表裏一致性,getSongs 表示獲取歌曲,並沒有暗示這個函數會更新頁面,但是實際上函數更新了 div,這就是表裏不一,正確的寫法是

      • 要麼糾正函數名

          function getSongsAndUpdateDiv(){
              return $.get('/songs).then((response){
                  div.innerText = response.songs
              })
          }
        
        
      • 要麼寫成兩個函數

          function getSongs(){
              return $.get('/songs)
          }
          function updateDiv(songs){
              div.innerText = response.songs
          }
          getSongs().then((response)=>{
              updateDiv(response.songs)
          })
        
        
    • 時間一致性
      有可能隨着代碼的變遷,一個變量的含義已經不同於它一開始的含義了,這個時候你需要及時改掉這個變量的名字。
      這一條是最難做到的,因爲寫代碼容易,改代碼難。如果這個代碼組織得不好,很可能會出現牽一髮而動全身的情況(如全局變量就很難改)

改代碼

如果你的代碼有單元測試,那麼改起來就很放心。如果沒有單元測試,就需要用「小步快跑」的策略來修改。

小步快跑的意思是說,每次只修改一點點,測試通過後,再修改一點點,再測試,再修改一點點……如此反覆。

那麼如何修改一點點呢?《重構》這本書介紹了很多方法,但是講得挺囉嗦的,如果你有時間可以看看。

我這裏只說兩個經久不衰的方法。

一、使用函數來改代碼

步驟:

  1. 將一坨代碼放到一個函數裏
  2. 將代碼依賴的外部變量作爲參數
  3. 將代碼的輸出作爲函數的返回值
  4. 給函數取一個合適的名字
  5. 調用這個函數並傳入參數
  6. 這個函數裏的代碼如果超過 5 行,則依然有優化的空間,請回到第 1 步

二、使用對象來改代碼

如果使用了函數改造法改造後,發現有太多的小函數,則可以使用對象講這個函數串起來。

記得我們講過「this 是函數和對象的橋樑」嗎,我們會用 this 來串聯這個對象和所有函數。

最終代碼:http://js.jirengu.com/mimazaboke/1/edit?html,js,output

一些固定的套路

  1. 表驅動編程(《代碼大全》裏說的)
    所有一一對應的關係都可以用表來做
  2. 自說明代碼(以 API 參數爲例)
    把別人關心的東西放在顯眼的位置

bad smell(壞味道)

有些代碼可以用,但是很「臭」。

哪些代碼是有壞味道的

  1. 表裏不一的代碼
  2. 過時的註釋
  3. 邏輯很簡單,但是看起來很複雜的代碼
  4. 重複的代碼
  5. 相似的代碼
  6. 總是一起出現的代碼

破窗效應

此理論認爲環境中的不良現象如果被放任存在,會誘使人們仿效,甚至變本加厲。一幢有少許破窗的建築爲例,如果那些窗不被修理好,可能將會有破壞者破壞更多的窗戶。最終他們甚至會闖入建築內,如果發現無人居住,也許就在那裏定居或者縱火。一面牆,如果出現一些塗鴉沒有被清洗掉,很快的,牆上就佈滿了亂七八糟、不堪入目的東西;一條人行道有些許紙屑,不久後就會有更多垃圾,最終人們會視若理所當然地將垃圾順手丟棄在地上。這個現象,就是犯罪心理學中的破窗效應。

程序員要做到:只要是經過你手的代碼,都會比之前好一點。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章