論代碼中爲何不該當寫註釋

當不少前輩教育後輩應當多寫註釋的時候,當網絡上充滿了有關程序員從不寫註釋的段子的時候,這是一個很是有爭議的話題。做爲一個標題黨,容我先修正一下個人觀點:我認爲若是代碼寫得足夠好,那麼大多數註釋是多餘的,咱們應該經過寫出更好的代碼來代替更多註釋。前端

註釋的確有其用途,但大部分狀況下,程序員在濫用註釋。我是反對夾雜在代碼間的註釋的,我認爲註釋應當從代碼中獨立出來——一般被稱爲文檔。程序員

請看下面一段代碼。數據庫

/* /static/market/checkout.js

2014.7.2 create by orzfly
2014.7.29 update by jysperm: fixbugs

TODO: 這段代碼中註釋太多了,須要移除一些 -- jysperm
*/

var raw_products = req.query['products'].split(',');

// 商品 ID 的數組
var products = []

// 過濾每一個參數
for(var i = 0, i < raw_products.length, i++) {
    if (!raw_products[i]) 
        return;

    // 前端傳來的數據中竟然會有空格
    if (!raw_products[i].trim())
        return

    /* 2014.7.22: 如今可使用非數字 ID 了
    // 略過非數字條目
    if (isNan(raw_products[i].trim().toFixed()))
        return;
    */

    products.push(raw_products[i].trim().toFixed());
}

// 總錢數
var sum = 0;

// 計算每一個商品的總錢數
for(var i = 0, i < products.length, i++) {
    // 從數據庫中查商品信息
    var data = db.product.byID(products[i]);

    // TODO: 誰來寫一下沒查到商品的狀況

    // 把商品的價格加到總錢數上, a += b 是 a = a + b 的縮寫
    sum += data.price;
}

你竟然花了一半的時間在讀註釋上面,這是多麼浪費生命的事情,在代碼中每加一行註釋,都會增長代碼的閱讀成本——即便閱讀者已經瞭解了註釋所要傳達的精神;同時也會增長維護成本:修改這段代碼的人不得不連同註釋一塊兒修改——並且你不能肯定他到底會不會這麼作。數組

因此只有當很是必要的狀況下,才應該添加註釋,並且應當言簡意賅。註釋不該當解釋一段代碼在作什麼,由於這是每一個合格的程序員都應該知道的事情,而是應該解釋這段代碼爲何要這樣作。網絡

由此引出幾種明顯不該該添加的註釋:函數

  • 本應由版本控制系統記錄的信息、對代碼的評論,以及不是很重要的 TODO.版本控制

    代碼並非所有,一個但凡靠譜一點的項目,都應當有本身的版本控制系統,除了記錄代碼差別以外,還應該有工單和 Issue 的功能。
    閱讀代碼的人一般不須要了解幾個程序員之間的恩怨,不少時候也不關心這段代碼的歷史,這些信息只會把代碼拖得愈來愈長。code

  • 廢棄的代碼文檔

    被棄用的代碼應該被刪掉,這些代碼會很是影響閱讀,並且它們通常又很長。
    在絕大多數狀況下,被棄用的代碼不會從新派上用場,即便出現了少數狀況,你也能夠從版本控制系統中找到它們。get

  • 對變量和函數名的解釋

    這種狀況下顯然你須要一個更恰當的名字,若是這個標識符有一個比較小的做用於,你可使用一個比較長的名字以便容納更多信息。

    例如上文中的:

    • products 應改成 products_id
    • sum 應改成 total_amount
    • data 應改成 product_record
  • 對語法的解釋,以及顯而易見的事情

    例如上文中的「把商品的價格加到總錢數上, a += b 是 a = a + b 的縮寫」,這顯然是任何一我的都知道的事情。

    也許有人願意經過寫這樣的註釋來梳理思路:

    // 過濾參數:
    //    去掉 ID 裏的空格
    //    去掉非數字 ID
    // 循環每個商品:
    //    去數據庫查記錄
    //    把商品的價格加到總錢數上

    可是當代碼寫完的時候記得刪掉。

  • 對邏輯塊的歸納

    例如上文中的「過濾每一個參數」和「計算每一個商品的總錢數」,這狀況下一般是你沒有對邏輯進行抽象,具體表現就是像下面這樣:

    // 首先有 25 行代碼去作事情 A
    // 而後有 5 行代碼去作事情 B
    // 這裏有 90 行代碼去作事情 C
    // 最後有 45 行代碼去作事情 D

    這致使你須要一些註釋來分割這四個部分。若是這四個部分都是一個函數調用的話,那麼函數名自己就是對邏輯的一種解釋,讀者能夠快速地找到函數 B, 而沒必要在前 25 行中搜索作事情 B 的五行代碼。

綜上,我對這段代碼的改善意見以下:

var filterProductID = function(raw_products_id) {
    result = []

    raw_products_id.forEach(function(product_id) {
        if (product_id and product_id.trim()) 
            products_id.push(product_id.trim().toFixed());
    });

    return result;
};

var getPriceOfProduct = function(id) {
    var product_record = db.product.byID(products[i]);

    if (product_record)
        return product_record.price;
    else
        return 0;
};

var products_id = filterProductID(req.query['products'].split(','));
var tatol_amount = 0;

products_id.forEach(function(product_id) {
    tatol_amount += getPriceOfProduct(product_id);
});

雖然我在以一段虛構的,刻意編造的代碼來佐證個人觀點,但我相信在實際的項目中,一樣能夠經過改善代碼來減小注釋,並且整體上來說會節約更多的時間和精力。

http://jysperm.me/technology/1750

相關文章
相關標籤/搜索