Thursday, October 29, 2009

簡單的藝術

簡單的藝術
by thinker
2 Columns
關鍵字:
coding 軟體工程師
一般人,攏說咱是一陣軟體工程師。工程師的工作是在有現的時間加預算內,達成目標,無論方法。咁講,咁若達成目標這呢簡單。品質也是非常重要的因素,軟體的品質包括正確性、執行的效率和維護的成本。為著改善軟體的品質,軟體工程師,必需是藝家。藝術是以「巧妙」的方法,完整的傳達個人的想法和理念。「巧妙」是啥?「巧妙」是乎郎讚嘆的方法。咱用四兩撥千斤,這是「巧妙」。咱用大象搬樹,這就毋是「巧妙」。咱用「犀牛望月」就比「踮這一直等」來得「巧妙」。「巧妙」的方法,乎咱用簡單,又正確的方法,傳達咱的意念。寫程式也要同款。

programmer 若只是工程師,咱咁若會曉完成功能,但是得不著好的品質。好的品質,也就是用「巧妙」的方法完成工作。「巧妙」的方法毋是乎郎看無,也毋是一支嘴透腸仔底的方法。「巧妙」是用容易瞭解的方法,完成簡短、正確的結果。若是偏離了「容易瞭解」或者是「簡短、正確」,這就毋是「巧炒」。

譬如講,base64 的解碼演算法,查表就比 if-else 巧妙:

static const char Base64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static const char Pad64 = '=';

......... skip ............

while (2 < srclength) {
input[0] = *src++;
input[1] = *src++;
input[2] = *src++;
srclength -= 3;

output[0] = input[0] >> 2;
output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
output[3] = input[2] & 0x3f;

target[datalength++] = Base64[output[0]];
target[datalength++] = Base64[output[1]];
target[datalength++] = Base64[output[2]];
target[datalength++] = Base64[output[3]];
}

.................. skip ...........

那是將查表的部分,改成用 if-else 的 condition,會使得程式更加複雜,難了解。雖然查表的方法,看起憨憨,要將每一個字母攏寫出,但是對於讀程式碼的人來說,一看就知,容易了解,而且無影嚮著執行的效率。這就是「巧妙」。

將:

output[0] = input[0] >> 2;
...... cut ....
target[datalength++] = Base64[output[0]];
...... cut ....

改成:

target[datalength++] == Base64[input[0] >> 2];

並無恰「巧妙」,顛倒是每一行所內含的意義變多,程式較無容易了解。原來的方法可能恰多行,但是對讀的人來講,簡單多啊! 你可能會認為,後壁的方法己經很習慣啊! 但是你要考慮著,並毋是每一個人攏習慣用這種方法。Keep It Simple and Stupid (KISS) 也就這個意思,盡量用簡單的方法寫你的 code。

所謂的簡單,是講讀者容易了解的方法。踮這咧 OO 的年代,真多人對著繼承 (Inherent) 有著很大的寄望,以為盡量繼承,就會使減少程式碼的量,更加容易維護。這致使真多郎,毋管什麼麼件,只要有同款的部份,攏會繼承。繼承會講求目的和理念。若是沒一套合理的目的和理念,繼承就沒脈絡也尋。歸個繼承系統,也因此難以了解。所以,繼承也愛講求「巧妙」,巧妙的繼承,是將物件依照一定的道理分類,而不是依照程式碼的重複的程度來繼承。依照程式碼的重複的程度來做繼承,會使著繼承系統無脈絡可尋,讀者也就難以了解。繼承也毋通太深。太深的繼承,會使著物件難以了解。對讀者來講,要了解一個物件的行為,就要追蹤繼承樹上每一個被繼承的 class。太深的繼承,對讀者而言,是一種負擔,會使得程式難以維護。這款情形,就算是設計者,在離開一段時間後,回頭看自己設計出的麼件,也會霧煞煞!

Indent (縮排)對程式也是很重要的,哪是沒 indent,大部分程式攏難以了解。「巧妙」的程式,也要有「巧妙」的 indent。我建議最少四個空白以上的 indent。有一寡人是不知 indent 的,有的人很凍酸,縮白是一二個空白的寬度。indent 是會乎讀者容易了解,也乎自己容易 debug,減少錯誤。曾經有一個朋友,伊攏用一個空白做 indent。伊講按哪才會使在有限的空間內,擠恰多麼件。我講按咧恰容易發生錯誤,伊講不。我進一步問,發現伊其實也常常看著毋對行。一來,咱無應該將每一行程式寫太長。二來,槽狀也毋通太深。三來,四格以上的寬度,恰不看毋對。

程式內的註解,嘛要「巧妙」。多役的說明,只會困擾著讀者。其實,當著開始看程式的內容的時陣,咱只會注意著程式的本文,註解的部份會自動乎咱跳過,不去注意著。多役的說明,只會打擾著讀者,讀者希望可以在一個畫面內,盡量看著恰多的資料。按咧安排的程式,讀者嘛讀恰順,恰容易了解。所以,註解盡量短小、簡單,毋通乞吃趕廟公,顛倒打擾著讀者的節奏。

除了程式本身之外,架構(河洛話要按怎寫恰好?)的設計也要「巧妙」。巧妙的設計,用簡單的架構來解決複雜的問題。簡單的設計,乎人容易了解。要設計出複雜的麼件並無困難,按怎找出簡單的設計,解決複雜的問題,才是「巧妙」。可以使用 client-server 解決的問題,就無需要用 peer-to-peer。通使用 hash table 解決的問題,就無需要用 rb-tree 去解決。一切,以著簡單為水。

一切攏要保持簡單,保持簡單就是一種藝術。藝術家,所追求的就是「巧妙」的傳達伊的意念。嘛要有藝術的精神,才能求得最高境界的「巧妙」。也著是講,好的 programmer 必需是一個藝術家,以著「巧妙」的簡單藝術手法,傳達你的意念乎看程式的人。

No comments: