2. 程式撰寫風格的指導原則

對一個一百行的程式進行偵錯很容易,對一千行的程式就難了許多,到了一萬行的程式,如果程式不曾經過系統化地予以組織,幾乎是不可能偵錯的。一致化的程式撰寫風格對大型程式的維護十分重要,而它對於一個由多人發展或是需要長時間維護的專案而言,更是無比地重要。

發展一套程式撰寫風格的用意在於使程式能夠一致而且清楚,好的程式撰寫風格不僅減少了程式錯誤(bug)發生的機會,也可以減短閱讀和了解程式碼所需花費的時間。程式撰寫風格的指導原則必須著眼於命名方法、型別檢查、有效範圍和註解等主題。請記住下列的指導原則:

請牢記這些原則,讓它們成為你想都不用去想的習慣。本章將要就這些原則加以討論並且介紹其中的細節。

具描述性的命名方法
 

過去這幾年,許多人紛紛提出了各種不同的程式撰寫標準,有些相當不錯但有些並不十分有用。如果你養成了一個好習慣,採用簡單而且標準的方法來撰寫程式,你就會因為你的程式易讀易懂而出名。如果你是在一個程式設計團隊中工作,易讀易懂的程式碼可以大幅地增進團隊的整體生產力。

控制項名稱的字首
 

在為控制項變數取名字時,請以三個字母作為控制項名稱的字首,讓這三個字母的字首代表該名稱所引用的控制項種類,這種命名方式可以增進程式碼可讀性。想想看,如果把某個事件程序命名為Buffalo_Click,有誰能夠猜想得出來Buffalo所引用的是何種控制項?然而,如果把它改成cmdBuffalo_Click,那麼我們可以很容易地就知道它在引用指令按鈕控制項(CommandButton Control),而picBuffalo_Click所引用的是一個圖片方塊控制項(PictureBox Control )。這裡有一份廣為接受的標準字首,我們把它列在下面:

代表VISUAL BASIC控制項名稱的字首
字首 控制項
ado ADO Data
ani Animation
cal Calendar
cbo Combo box
ch Chart
ch3 3D check box
chk Check box
clp Picture clip
cm3 3D command button
cmd Command button
com Comm
con Container (DAO)
ctr Control (specific type unknown)
dat Data
db Database (DAO)
dbc DataCombo
dbd DataGrid
dbe Database engine (DAO)
dbgrd Data Bound Grid
dbl DataList
dir Directory list box
dlg Common dialog box
doc Document (DAO)
drv Drive list box
drp DataRepeater
dtp DTPicker
fil File list box
fld Field (DAO)
flex Hierarchical FlexGrid
rm Form
fsb FlatScrollBar
gau Gauge
gpb Group push button
grp Group (DAO)
hdr Header
mg Image
imgcbo ImageCombo
ix Index (DAO)
key Key status
lbl Label
lin Line
lst List box
lsw ListView
lwchk Lightweight check box
lwcbo Lightweight combo box
lwcmd Lightweight command button
lwfra Lightweight frame
lwhsb Lightweight horizontal scrollbar
lwlst Lightweight list box
lwopt Lightweight option button
lwtxt Lightweight text box
lwvsb Lightweight vertical scrollbar
mci Multimedia MCI
med Masked Edit
mnu Menu
mpm MAPIMessages
mps MAPISession
mst Tabbed Dialog
mvw MonthView
ole OLE
op3 3D option button
opt Option button
out Outline
pic Picture box
pnl 3D panel
prg ProgressBar
prm Parameter (DAO)
qry QueryDef (DAO)
rd RemoteData
rec RecordSet (DAO)
rel Relation (DAO)
rtf RichTextBox
shp Shape
sld Slider
spn Spin button
sta StatusBar
ssys SysInfo
tbd TableDef (DAO)
tbs abStrip
tlb Toolbar
tmr Timer
tre TreeView
txt Text box
usr User (DAO)
vsb VScrollBar
wsp Workspace (DAO)

一般的變數名稱
 

有些人(特別是C程式設計師們),建議應該用Hungarian Notation字首來為所有變數命名,這種命名的標準類似於前面提到的控制項名稱字首。筆者不盡完全贊同這種建議。從好的一面看來,當你看到變數時,就可以知道其資料型別,這是一項優點;然而在另一方面,這種命名方式有時候可能反而會寫出較難閱讀的程式。

Microsoft Basic的程式設計師從很早以前就可以用變數名稱的字尾來代表資料型別,例如X% 代表一個整數,X! 是個單精準浮點數,而X$ 則是個字串。這種命名方式與Hungarian Notation字首命名方式孰優孰劣並不一定,這只是個人意見的問題。

以下這張表列出了代表各種資料型別的字尾,另外也列出了新的資料型別,不過它們沒有代表的字尾,這支持了筆者的一個論點─ Microsoft已經漸漸不用這些字尾。

代表資料型別的標準字尾
字尾 資料型別
% 2-byte signed integer
& 4-byte signed integer
@ 8-byte currency
! 4-byte single-precision floating-point
# 8-byte double-precision floating-point
$ String
(無) Boolean
(無) Byte
(無) Collection
(無) Date
(無) Decimal (a 12-byte Variant)
(無) Object
(無) Variant

也許你會認為全盤採用Hungarian Notation字首才是一個好方法,因此,我們也把建議使用的字首列在下面。請注意,有些資料型別會用多個字首來代表,這讓你能夠追蹤變數的用途。例如,標準的16位元含正負數的整數可能是Boolean、Handle、Index、Integer或是Word。

代表各種資料型別的Hungarian Notation字首
字首 資料型別
bln Boolean
byt Byte
cur Currency
dbl Double
dec Decimal
dtm Date (Time)
sng Float/Single
h Handle
i Index
lng Long
int Integer
obj Object (generic)
str String
u Unsigned quantity
ulng Unsigned Long
vnt Variant
wrd Word

上表中的Collection和Object資料型別泛指一般的物件集合和所有的物件,而不是某個具有特定型別的集合物件(Collection)和特定的物件。舉個例子來說,某個程序可能會收到一個物件作為它的參數,但這個程序可能不知道該物件確切的資料型別,因此你會用obj字首。當你知道某個物件的型別時,請用代表該物件類別的字首(請看後面的 物件類別名稱 )。

變數的宣告
 

在本章一開始就提到的指導原則中,其中有一項是使用Option Explicit陳述式。你可以讓VISUAL BASIC在產生任何一個新的模組時,自動幫你加入Option Explicit陳述式──從「工具」功能表中選擇「選項」,在「選項」對話方塊中點選「編輯器」頁籤,然後核取「要求變數宣告」。

Option Explicit陳述式強迫你必須在使用變數之前先宣告變數。你應該在Dim陳述式中明確地宣告變數的型別,這樣,變數名稱就會較容易閱讀,也較容易和其他控制項名稱和物件名稱有所區別。而且,只要在模組的開頭處稍微看一下,就可以知道變數的資料型別。


警告

許多人(尤其是C程式設計師)常犯的一個錯誤是:把好幾個同樣的資料型別的變數放在同一行宣告陳述式中,但只用一個As關鍵字。這樣做很可能無法得到你預期的結果。


以下這兩行宣告變數的陳述式不會有問題:

Dim intA As Integer, sngB As Single, dblC As Double
Dim D%, E!, F#

然而,以下這行陳述式宣告了兩個Variant變數(intI和intJ)以及一個Integer變數(intK )A而不是三個Integer變數:

Dim intI, intJ, intK As Integer

這樣,程式可能無法產生你預期的結果(除非你有意設計成這樣),而且很難找到錯誤發生的原因。

功能表
 

為功能表選項命名的方法也有好幾種,我們選擇的是以新標準的mnu字首來為功能表選項命名。你可以多加一些文字來描述某個功能表選項與哪一個下拉式功能表相關。例如,在「說明」功能表中的「關於」選項可以被命名為mnuHelpAbout。本書則採取比較簡單的原則,以上例來說,我們會以mnuAbout來代表該選項。在本書中看到以mnu為字首的名稱時,這個名稱必定是代表功能表選項。

物件類別的名稱
 

當你在建立一個物件類別時,請以一個具有描述性的名稱來為該物件類別命名;而對於這個物件類別所產生的物件,請用代表物件類別的字首為該物件命名。一般而言,代表某個物件類別的字首是三個字母,但如果有必要的話,可以用較長的字首。Microsoft的建議是:在為物件類別命名時,請用整組字詞並保留每個字的開頭大寫,如下表所示:

物件類別命名方法和物件命名方法的範例
物件類別 物件名稱的字首 範例物件
Loan lon lonBoat
Planet plnt plntEarth
EmployeeRecord erc ercSales
DailySpecial dspec dspecTuesday

檢查資料型別
 

你應該儘量讓每一個變數使用合適的資料型別,但這並不表示你應該用"佔最少記憶體"的資料型別;例如,Boolean資料型別本來只需要一個位元就可以了,但事實上Boolean變數所佔的長度和Integer一樣,都是兩個位元組。

為什麼要浪費多餘的位元呢?答案是"小"不如"安全"來得重要。即使程式要在Internet上面執行,必須顧慮資料傳輸的速度,但是"安全"還是比"小"更重要。因此,最好是用合適的資料型別,使程式更安全、更容易被人了解。Boolean變數的值不是True就是False,而Byte變數(VISUAL BASIC中最小的型別是Byte)也可以含True或False,但是使用Boolean變數會使程式更清楚也因而更安全。

在宣告物件變數時,使用合適的資料型別尤其顯得重要。如果你用一個明確的物件類別來宣告一個物件變數,而不是用一般性的Object或Collection型別,那麼編譯器可以把物件的使用予以最佳化(有關這部分的細節請看 第二十四章"在其他應用程式中執行的ActiveX物件" )。

請記得務必在程序中指明參數的資料型別,這可以幫助你偵測到使用程序時發生的錯誤。另外,請記得除了Variant型別之外,其他型別都可以作為Optional參數的型別,這是VISUAL BASIC 4所沒有的特性。

劃分有效範圍
 

有效範圍(Scope)是指變數、程序或是物件的可視程度(Visibility),也就是這些項目在應用程式中可運作的範圍。在老舊的程式中,所有的變數都是全域的,也就是說,你可以在程式的任何一處改變變數所含的值。後來當Basic增加了副程式(Subroutine)和函式程序之後,對於某個程序而言,資料就有了局部性和全域性的分別了。現在VISUAL BASIC有四個層次的有效範圍:

  •  萬用層次(Universal) :可以透過ActiveX在其他應用程式中運作
     
  •  全域層次(Global) :可以在專案中所有模組下的所有程序中運作
     
  •  模組層次(Module) :可以在同一個模組中所有的程序裡運作
     
  •  局部層次(Local) :只能在該變數所在的程序中運作
     

限制某個項目的有效範圍可以控制對這個項目的使用方式,有效範圍愈廣,就必須愈小心使用。你應該盡可能地縮小項目的有效範圍。事實上,使用屬性程序(Property Procedure)可以讓程式完全不需用到全域變數,這些屬性程序比全域性資料還多了一層控制;它們可以檢查所收到的資料是否合法,以及檢查原呼叫程序是否有權利修改資料。

在程式中撰寫註解行
 

好的程式註解對一個負責維護程式的人來說真的是一大福音。這裡有一些協助你撰寫程式註解行的原則可供參考:

  • 在程序的開頭說明程序所做的事,並且列出這個程序所用到的全域變數及其他程序。
     
  • 在Case陳述式和其他決策結構之前,簡單地描述所有的選擇以及可能採取的行動。
     
  • 在迴圈之前描述迴圈內的動作以及跳出迴圈的條件
     
  • 用"假設:"或"ASSUMPTION:"等字樣標示你在該處作了一個假設,然後以簡短的文字說明這個假設。如果在程式撰寫的過程中,遇到不能決定的部分,先用"未完成:"或"UNDONE:"來標示,以後再用編輯器的「尋找」功能找到這部分予以完成。
     

其他相關資訊
 

在Visual Basic線上手冊中,可以找到更多有關標準命名方法和程式撰寫風格的資訊。如果你是在一個很大的程式設計隊伍中工作,而且程式風格標準化對你是個重要課題,那麼這片光碟所提供的資訊十分值得參考。許多公司和程式設計師都已經採用了這片光碟中所提供的標準,因此,似乎沒有必要再去創建出自己的一套標準。