筆者在就學時,讀的是電子工程而不是資訊工程,所以在寫程式上,其實還是和所謂資工系的高手有一段落差,這在上班時,會有很明顯的認知,尤其是在分工清楚的公司,更甚明顯。不過畢竟術業有專攻,大家也別太枉自匪薄,只要多看,注意一些小細節,總是會有機會的。
以寫程式為例,電子工程相關的人的心態是:
可以動就好。而資訊工程講求的是程式的高閱讀性和維護性。所以今天我們要探討的就是如何讓程式保有高閱讀性和維護性。
以下是一個非常簡單的程式,或許compiler 不會過,但只要抓到重點就可以了:
if(test_flag1==1){
test_data=1;
}
else if(test_flag2==0){
test_data=2;
}
else{
test_data=0;
}
以上的程式,盡可能的讓程式碼「擠」在一起,雖然版面可以塞得下較多的程式,但因為都滿擠的,當程式看久了,常常會讓眼精非常的吃力。而且如果不了解數值的內容的話,閱讀上就會很辛苦。大家不仿可以試試看下面的寫法:
#define
TRUE 1
#dfeine
FALSE 0
#define
FRUIT_APPLE 0
#define
FRUIT_BANANA 1
#define
FRUIT_GRAPAS 2
if ( TRUE == test_flag_1)
{
test_data
= FRUIT_BANANA;
}
else if ( FALSE == test_flag_2)
{
test_data
= FRUIT_ GRAPAS;
}
else
{
test_data
= FRUIT_ APPLE;
}
不知道個位客倌有沒有覺得上面的寫法比較容易閱讀且容易維護,(謎之音: 你虎爛。), 沒關係,
就讓筆者慢慢解說上面的程式有幾件事的差別。
差別1:擠在一起常常會有搞混的情況發生,盡可能的讓程式中間穿插空白,增加閱讀的方便性。
差別2: 盡可能的讓常數使用巨集(#define)的方式,定義一個有意義的名稱。
這邊要有2個地方值得注意:
(a)常數最好使用大寫的英文,因為這是一個不成文的規定,所以以後你在閱讀別人的程式時,遇到大寫時,第一直覺就可以知道這是「常數」。
(b)相同的巨集,最好前面帶有一個表示相同類型使用到的英文,以避免亂用巨集的情況發生,導致閱讀的混亂(就是呼叫到不該呼叫的巨集)。
差別3,大括號(「{ }」 最好分2行, 因為有專案開發時,常常會遇到需要把判斷式省略或是做測試使用。
舉個簡單舉子:如果我要讓test_data
永遠都只會是” FRUIT_
APPLE” 的話, 那麼這時候我會這樣做:
#if 0
if ( TRUE == test_flag_1)
{
test_data
= FRUIT_BANANA;
}
else if ( FALSE == test_flag_2)
{
test_data
= FRUIT_ GRAPAS;
}
else
#endif
{
test_data
= FRUIT_ APPLE;
}
這樣的好處就:
(a)
非常好加入巨集的維護,而且可以很方便的啟用(enable)與關閉(disable)
(b)
如果有版本控制軟體的話(SVN/Mercurial/GIT),在比較程式不同時,只會發現多出來的巨集(#if 0/ #endif),這在專案維護上非常重要。
差別4:
判斷式的寫法:
if (
TRUE == test_flag_1) 和 if (test_flag_1 == TRUE)
建議遇到常數時,盡可能的養成常數寫在判斷式的左側,以防止筆誤造成的除錯上的困難。
(a)
if (test_flag_1 0 = TRUE) ç 筆者不小心寫錯,但這樣compiler會過,而且會永遠成立,因為判斷式非0即真。
(b)
( TRUE = test_flag_1) ç 筆者不小心寫錯,但這樣compiler會出現錯誤。因為常數沒有辦法被設定成另一個數值。
這個是一個非常重要的小技巧,可以防止筆誤的機率。
以上分享給大家知道,並且歡迎大家討論。
感謝沒事才做木工大大的提醒,在寫這篇文章的時候,到是沒有認真思寫這裡的變數使用方式,假設變數都只有TRUE或是FALSE的話,那麼到是可以換個方式寫:
if ( test_flag_1)
{
test_data
= FRUIT_BANANA;
}
else if ( !test_flag_2)
{
test_data
= FRUIT_ GRAPAS;
}
else
{
test_data
= FRUIT_ APPLE;
}
其實有時候在寫程式時,也是希望可以讓程式短一點,這樣可以少寫一點或是讓版面可以更精簡一點。