天天看點

約定優于配置——軟體開發的簡約原則 約定優于配置——軟體開發的簡約原則

約定優于配置——軟體開發的簡約原則

2012-09-15 13:32  原文  簡體  繁體   5,099 次圍觀

工作快滿 1 年了。在剛從 CUHK 畢業的時候,我還滿懷悲壯地表示在中文大學飽受摧殘,各種 assignments projects 所寫的代碼已經超過了整個在武大的四年。而現在,wc -l 顯示的數字已經可以讓我十分蛋定,這一年的代碼量已經超過了過去所有學生時代的總和。回過頭來看一年前寫的代碼,真是慘不忍睹,恨不得把當時的自己拉出去暴打一頓。确實走了很多彎路,但我也是以收獲頗豐。

感觸之一就是怎樣編寫漂亮整潔的代碼。我曾經說過,我是個完美主義者,寫部落格的時候我要檢查以防出現錯别字,寫代碼的時候我會特别注意變量命名是否規範,甚至代碼縮進是否對齊。這大概已經屬于強迫症的治療範圍了。在現實項目開發中,整潔漂亮 意味着用最少的代碼,實作完整的業務功能,同時代碼是易于了解的。然而随着時間流逝代碼不斷被修改,系統設計的整體結構則逐漸衰弱。編碼從嚴謹的工程堕落為随性地胡亂砍劈。不重構,軟體就會慢慢腐爛。這一切是如何發生的呢?

歸根到底,還是源于軟體開發人員惰性。懶惰是天生的,例如 sofish 舉例過的一段代碼——

if(condition_a) {
    var str = condition_a.trim().replace(/^{(\w+)}$/, function(match){
        // ...
    });
} elseif(condition_b) {
    var str = condition_b.trim().replace(/^{(\w+)}$/, function(match){
        // ...
    });
} elseif(condition_c) {
    var str = condition_a.trim().replace(/^{(\w+)}$/, function(match){
        // ...
    });
} else {
    var condition = defaultValue;
        str = condition.trim().replace(/^{(\w+)}$/, function(match){
        // ...
    });
}
           

如果又有新的 condition_d,懶人複制粘貼一下就搞定。你可以同樣改成 switch,但本質上都是在寫重複的代碼。DRY 原則,即 Don’t Repeat Yourself,是編寫高品質代碼毫無疑問最重要的原則,重複是所有邪惡的來源。上面的代碼可以稍作修改

function dry(condition) {
    condition = condition || defaultValue;
    condition.trim();
    return condition.replace(/^{(\w+)}$/, function(match){
        // …
    });
}
 
if(condition_a) {
    dry(condition_a);
} elseif(condition_b) {
    dry(condition_b);
} elseif(condition_c) {
    dry(condition_c);
} else {
    dry();
}
           

将重複的邏輯提取出來,抽象為一個獨立的函數,看上去就幹淨漂亮很多。是以抽象是一個很重要的能力。說一個差勁的程式員懶惰,并不是指他不情願編碼,事實上,他正不遺餘力的敲打鍵盤;懶惰展現在不願意思考,不想碰架構優化現有的系統。

為什麼需要架構?

架構是當事情變得複雜之後必須考慮的問題。如果你的桌上有 2 本書,那麼你怎麼擺放其實沒關系,你随手翻翻也能很快找到你想要的段落。如果你有幾百本書,那麼你就需要一個書架了。如果是一個圖書館,那麼就更需要一個合理的規劃,将書本分門别類,編号,建立索引,友善查找。軟體開發是一樣的道理,你得知道系統将要到一個什麼樣的規模,提前做好各方面的約定。例如選用一套開發架構,指定團隊的代碼規範。

約定優于配置

這是 maven 最核心的設計理念,很多語言架構都将其思想發揚光大。遵循約定雖然損失了一定的靈活性,不能随意安排目錄結構,不能随意進行函數命名,但是卻能減少配置。更重要的是,遵循約定可以幫助開發人員遵守建構标準。

例如 Yii 的典型項目結構是:

projectName/
   index.php                 Web 應用入口腳本檔案
   assets/                   包含公開的資源檔案
   css/                      包含 CSS 檔案
   images/                   包含圖檔檔案
   themes/                   包含不同風格的主題
   protected/                受保護的應用檔案,主要代碼在這裡面
      components/            包含可重用的使用者元件,自定義類等等
         Controller.php      所有控制器類的基礎類
         Identity.php        用來登入認證的 'Identity' 類
      config/                包含配置檔案
         main.php            Web 應用配置
      controllers/           包含控制器的類檔案,MVC 中的 C
         SiteController.php  預設控制器的類檔案
      data/                  包含示例資料庫
         schema.mysql.sql    示例 MySQL 資料庫
      extensions/            包含第三方擴充
      messages/              包含翻譯過的文本,适用于多國語言支援
      models/                包含模型的類檔案,MVC 中的 M
         LoginForm.php       'login' 動作的表單模型
      tests/                 包含測試腳本
      views/                 包含控制器的視圖和布局檔案,MVC 中的 V
         layouts/            包含布局視圖檔案
            main.php         所有視圖的預設布局
            column1.php      使用單列頁面使用的布局
            column2.php      使用雙列的頁面使用的布局
         site/               包含 'site' 控制器的視圖檔案
            index.php        'index' 動作的視圖
            login.php        'login' 動作的視圖
      

又例如 Yii 中對于 action 通配符的規範,XyzController.php 中若有一個名為 actionEdit() 的方法,那麼展現在網頁 URL 上,就是是除去 action 字首的動作函數名。即 http://www.mydomain.com/xyz/edit

更多的規範還包括變量、函數和類使用駝峰命名風格,即每個單詞的首字母大寫并連在一起,中間無空格。變量名和函數名第一個單詞全部小寫,而類的首字母需要大寫,例如:$basePath, runFunction(), LinkPager。對 private 變量和函數來說,以下劃線作為字首,例如 $_actionList

當然還有資料庫的規範——

  • 資料庫表名和列名都使用小寫命名。
  • 名字中的單詞應使用下劃線分割 (例如 product_order)。
  • 對于表名,你既可以使用單數也可以使用複數。但不要同時使用兩者。為簡單起見,推薦使用單數名字。

如果風格統一,那麼代碼将是有規可循的。我們可以根據命名了解結構,根據結構了解建構的代碼原理。團隊的合作将是無縫的,多人 debug 也将沒有障礙。

我之前做的一個項目,就是因為缺乏遵循規範,而花費了大量時間和精力去做适配不一緻的接口參數,各種變量名稱的轉換占了整個項目代碼的很大部分。親自動手寫好一個站點并自己進行代碼維護,了解其中的弊端,經曆無數次的捶胸頓足痛定思痛,才知道最終如何改進才算架構“合理”。

關于重構

進度預估實際上是比較困難的一件事情。每當 Leader 問我這個子產品要幾天搞定時,我都支支吾吾。因為有時需要對舊代碼進行改造,或者說重構,而這些工作對于功能上沒有任何産出效益。在版本釋出的重壓下,快速疊代隻是我個人的一個期望而已。

軟體開發已經進化為軟體設計。在設計當中應當注重簡約的原則,少就是多。按照一定的設計模式來建構,總能達到事倍功半的效果。例如使用繼承、多态等面向對象手段,還有廣泛采用的工廠模式等等。又例如每個函數都簡單到僅僅 3 到 4 行長,函數的縮進層級不多于三層,每個函數隻做一件事,可複用,同時充分解耦。

好的代碼需要打磨。一個優秀的程式員,總能保證每一次 commit 倉庫裡的代碼比上一次更好。

關于技術布道

Fenng 曾經談過關于 技術布道 的一些經驗,其實就是“用影響影響影響”。那些大牛們孜孜不倦地對外傳遞大公司的動态、新的技術趨勢以及他們自己對技術的思考感悟,用自己的影響力去影響一部分具備影響力的人,再促使這部分人自發的去影響更大的目标群體。一些人之是以更牛是因為他們專注于自己做的事情,認為它是重要的,滿懷熱情,是以他有動力去優化自己的工作。相比之下更多的人隻不過是在應付。

我沒有那些令人景仰的牛人的魅力,我所能做的,隻是把自己所知道的總結出來,教給和自己合作的開發者,讓他們也能在技術上有所提升,這樣合作起來也會更輕松。我想這是件令人愉快的事情。

參考連結:

MVC架構導緻的詞彙表分裂

每一件意義重大的小事——讀《代碼整潔之道》

繼續閱讀