代碼膨脹(英語:Code bloat)是指程式碼(可以是原始碼,也可以是機器碼)生成的程式檔案過大、執行緩慢或者有其他浪費資源的情況。代碼膨脹可能由編寫代碼的語言、編譯時所用的編譯器,或者編寫的程式設計師導致。代碼膨脹通常指原始碼過於冗長,由程式設計師的編碼習慣和程式語言的設計導致,代碼膨脹也可以指編譯後的代碼或者二進制檔案占用空間過大(膨脹)。

常見原因

編輯

通常來說,膨脹的代碼是由於程式設計師使用了較多的代碼行,而非使用了解決問題的最佳方案。

程式設計師寫出膨脹代碼的部分原因有:

  • 過度設計
    • 過度使用物件導向(OOP)結構,如類和繼承。這可能導致麻煩且混亂的設計,使代碼量多於必要。
    • 不正確的使用設計模式——物件導向的開發人員可能在不需要使用設計模式的地方強行使用,從而導致問題。
  • 沒有用適當的封裝方案使代碼可重複利用,導致代碼重複[1]
  • 宣告式編程——在命令式或物件導向語言中實現宣告式編程風格通常會導致代碼膨脹。
  • 過度的迴圈展開——不理智的過度最佳化效能。
  • 過度使用多重If條件語句——而沒有使用如尋找表

一些原生編譯器推導膨脹的例子包括:

  • 死代碼——代碼被編譯,但從未被使用。
  • 冗餘計算——重新計算已經計算過的表達式。這種冗餘計算經常在實現防止緩衝區溢位的「邊界檢查」代碼時產生。 尖端的編譯器只將其計算一次,使用常用子表達式消除英語Common subexpression elimination迴圈不變代碼外提技術消除冗餘計算。
  • C++中採用的模板系統的一些原生實現是編譯該語言的編譯器之不足之處的例子。實現此特性的原生編譯器可以為使用的每個資料類型引入一個模板類版本的方法。但是,這也導致被編譯的方法可能永遠不會被用到,導致代碼膨脹。更尖端的編譯器和連結器能檢測多餘的副本並將其丟棄,或者避免產生,從而減少膨脹。因而,使用能放棄死代碼英語Dead code的編譯器可以使模板代碼產生更小的二進制檔案。[2]

例子

編輯

下列JavaScript程式碼演算法有著大量的冗餘變數、不必要的邏輯,以及低效的字串連接。

// Complex 
function TK2getImageHTML(size, zoom, sensor, markers) {
    var strFinalImage = "";
    var strHTMLStart = '<img src="';
    var strHTMLEnd = '" alt="The map"></div>';    
    var strURL = "http://maps.google.com/maps/api/staticmap?center=";
    var strSize = '&size='+ size;
    var strZoom = '&zoom='+ zoom;
    var strSensor = '&sensor='+ sensor;    
   
    strURL += markers[0].latitude;
    strURL += ",";
    strURL += markers[0].longitude;
    strURL += strSize;
    strURL += strZoom;
    strURL += strSensor;
    
    for (var i = 0; i < markers.length; i++) {
        strURL += markers[i].addMarker();
    }
    
    strFinalImage = strHTMLStart + strURL + strHTMLEnd;
    return strFinalImage;
};

而相同的邏輯可以用下列方式更有效地表達:

// Simplified 
function TK2getImageHTML(size, zoom, sensor, markers) {
    var url = [ 'http://maps.google.com/maps/api/staticmap',
        '?center=', markers[0].latitude, ',', markers[0].longitude,
        '&size=', size,
        '&zoom=', zoom,
        '&sensor=', sensor ]; 
    for (var i = 0; i < markers.length; i++) {
        url.push(markers[i].addMarker());
    }
    return '<img src="' + url.join('') + '" alt="The map" ></div>';
}

不同語言的代碼密度

編輯

各種電腦語言代碼密度有著很大差別,以「緊湊」語言(例如領域特定語言微軟P代碼英語Microsoft P-Code執行緒代碼英語Threaded code)編寫的程式以及緊湊語言(以機器碼編寫)的直譯器通常比直接用機器語言編寫程式消耗更少的代碼量。

減少膨脹

編輯

減少代碼膨脹的一些技術包括:[3]

  • 重構經常使用的代碼序列為子程式,並從多個位置呼叫該子程式,而不是在各個位置上複製並貼上英語Copy and paste programming這段代碼。
  • 重新使用已經被編寫的子程式(可能利用附加參數),而不是從頭編寫它們的新代碼。

參見

編輯

參考資料

編輯
  1. ^ 存档副本. [2017-06-12]. (原始內容存檔於2017-05-31). 
  2. ^ hopl-may.dvi (PDF). [2017-06-12]. (原始內容存檔 (PDF)於2007-11-20). 
  3. ^ Code bloat. DocForge. [30 December 2009]. (原始內容存檔於2016-03-05).