WFU

2018年1月18日 星期四

Linus : 程式的品味




2016年,Linus在TED訪談時,向 Chris Anderson 提到程式的品味( Good Taste of code ). 大部分的人可能會訝異想程式也有味道可言。其實這跟寫作一樣,為什麼有些文章讀起來津津有味,有些文章不知所言。程式也是一樣,可讀性對於程式越來越重要,尤其當你跟其他人一起開發的時候,雙方如果能夠快速的了解你的程式碼,對於開發的效率大大地提昇。


這就是為什麼程式需要好的品味及易讀性。所以什麼是程式的品味?這裡他用了單向連結序列的程式為例子。分別用兩個不同的撰寫方式說明程式的品味,底下這兩種寫法都能夠實現相同的功能,但是對於程式碼的品味及可讀性卻大大不同。

差的程式品味


這是個很直覺的寫法,但是不好的部份在於程式碼最後要移除物件時,必須考慮物件是位於序列的開頭或者不是。
remove_list_entry(entry)
{
    prev = NULL;
    walk = head;

    // Walk the list

    while (walk != entry) {
        prev = walk;
        walk = walk->next;
    }

    // Remove the entry by updating the
    // head or the previous entry

    if (!prev)
        head = entry->next;
    else
        prev->next = entry->next;
}

好的程式品味


這裡可以看到程式碼的行為很單純,移除物件時,沒有上述的困擾,用簡潔的程式碼處理上述的兩種情形。
remove_list_entry(entry)
{
    // The "indirect" pointer points to the 
    // *address* of the thing we'll update
    
    indirect = &head;
    
    //walk the list, looking for the thing that
    // points to the entry we want to remove
    
    while ((*indirect) != entry)
        indirect = &(*indirect)->next;
    
    // .. and just remove it
    *indirect = entry->next;
}
這怎麼做到的?關鍵在於 indirect pointer,它初始值為序列的開頭( head )。那要移除的對象為序列的開頭或者序列中間的物件,情形會是如何?
  • 若移除開頭的物件( entry = head ),指標初始值為開頭,程式不會進入 while loop 而直接移除它並更新物件的順序,即更新開頭。
  • 若是移除中間的物件,程式會進入while loop 搜尋需序列中要移除的物件,一旦找到後,離開 while loop而直接移除它並更新物件的順序。

概念上是如此操作的,細節及程式碼可以參考Github裡面 santisbon, AkosUzonyi 跟我的修改如下


What makes good taste? by santisbon