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有四個層次的有效範圍:
限制某個項目的有效範圍可以控制對這個項目的使用方式,有效範圍愈廣,就必須愈小心使用。你應該盡可能地縮小項目的有效範圍。事實上,使用屬性程序(Property Procedure)可以讓程式完全不需用到全域變數,這些屬性程序比全域性資料還多了一層控制;它們可以檢查所收到的資料是否合法,以及檢查原呼叫程序是否有權利修改資料。
在程式中撰寫註解行
好的程式註解對一個負責維護程式的人來說真的是一大福音。這裡有一些協助你撰寫程式註解行的原則可供參考:
其他相關資訊
在Visual Basic線上手冊中,可以找到更多有關標準命名方法和程式撰寫風格的資訊。如果你是在一個很大的程式設計隊伍中工作,而且程式風格標準化對你是個重要課題,那麼這片光碟所提供的資訊十分值得參考。許多公司和程式設計師都已經採用了這片光碟中所提供的標準,因此,似乎沒有必要再去創建出自己的一套標準。