把記錄作為主要的數(shù)據(jù)結(jié)構(gòu)。記錄是Erlang 4.3 時(shí)才引入的一種帶標(biāo)記的元組(參看 EPK/NP 95:034)。它類似于 C 語(yǔ)言中的 struct
或 Pascal 中的 record
。
如果記錄將用于多個(gè)模塊,它的定義應(yīng)放在這些模塊所包括的一個(gè)頭文件中(帶有 .hrl
后綴)。如果記錄只用在一個(gè)模塊中,則它的定義應(yīng)位于定義模塊的文件的最前面位置處。
Erlang 的記錄特性可以保證數(shù)據(jù)結(jié)構(gòu)跨模塊的一致性,因此在模塊間傳遞數(shù)據(jù)結(jié)構(gòu)時(shí),接口函數(shù)應(yīng)使用記錄。
使用記錄特性所提供的選擇器(selector)和構(gòu)造函數(shù)(constructor)來(lái)管理記錄實(shí)例。不要使用明顯假定記錄是一個(gè)元組的匹配。范例如下:
demo() ->
P = #person{name = "Joe", age = 29},
#person{name = Name1} = P,% 使用匹配,或者......
Name2 = P#person.name. % 像這樣使用 selector
不要像下面這樣編程:
demo() ->
P = #person{name = "Joe", age = 29},
{person, Name, _Age, _Phone, _Misc} = P. % 不要這樣做
使用帶標(biāo)記的返回值。
不要像下面這樣編程:
keysearch(Key, [{Key, Value}|_Tail]) ->
Value; %% Don't return untagged values!
keysearch(Key, [{_WrongKey, _WrongValue} | Tail]) ->
keysearch(Key, Tail);
keysearch(Key, []) ->
false.
{Key, Value}
不含有 false 值。下面是正確的方法。
keysearch(Key, [{Key, Value}|_Tail]) ->
{value, Value}; %% Correct. Return a tagged value.
keysearch(Key, [{_WrongKey, _WrongValue} | Tail]) ->
keysearch(Key, Tail);
keysearch(Key, []) ->
false.
catch
和 throw
千萬(wàn)不要在搞不清用法的情況下使用 catch
和 throw
!要盡可能少地使用它們。
復(fù)雜與非信任輸入(從外部環(huán)境中所輸入的內(nèi)容,而非來(lái)自于可信的程序時(shí))可能會(huì)導(dǎo)致代碼很多深層次位置的錯(cuò)誤,當(dāng)程序處理這些類型的輸入時(shí),catch
與 throw
就顯得非常有用了。關(guān)于這一點(diǎn),典型的例子就是編譯器。
千萬(wàn)不要在搞不清用法的情況下使用 get
和 put
等函數(shù)!盡量少用它們。
引入一個(gè)新的參數(shù),就可以重寫使用進(jìn)程字典的函數(shù)。
范例如下:
不要像下面這樣編程:
tokenize([H|T]) ->
...;
tokenize([]) ->
case get_characters_from_device(get(device)) of % Don't use get/1!
eof -> [];
{value, Chars} ->
tokenize(Chars)
end.
正確的方法是:
tokenize(_Device, [H|T]) ->
...;
tokenize(Device, []) ->
case get_characters_from_device(Device) of % This is better
eof -> [];
{value, Chars} ->
tokenize(Device, Chars)
end.
使用 get
和 put
會(huì)容易導(dǎo)致,在同樣輸入下函數(shù)的結(jié)果卻隨情況不同而改變。這使得代碼難以閱讀,因?yàn)榇a已經(jīng)失去了確定性。調(diào)試也變得很復(fù)雜,因?yàn)槭褂?get
和 put
的函數(shù)不僅是自身參數(shù)的函數(shù),而且還是進(jìn)程字典的函數(shù)。Erlang 中的很多運(yùn)行時(shí)錯(cuò)誤(比如 bad_match
)就包括函數(shù)的參數(shù),但從來(lái)不包括進(jìn)程字典。
不要使用 -import
,使用它會(huì)讓代碼變得難以閱讀,這是因?yàn)闊o(wú)法弄清函數(shù)定義所在的模塊。使用 exref
(交叉引用工具)查找模塊依賴。
一定要搞清楚某個(gè)函數(shù)之所以導(dǎo)出的原因。這種原因可能包括以下幾種:
apply
、spawn
調(diào)用,但只限于本模塊內(nèi)部調(diào)用。 使用不同的 -export
進(jìn)行分組,并相應(yīng)對(duì)它們進(jìn)行注釋。范例如下:
%% 用戶接口
-export([help/0, start/0, stop/0, info/1]).
%% 模塊間導(dǎo)出
-export([make_pid/1, make_pid/3]).
-export([process_abbrevs/0, print_info/5]).
%% 導(dǎo)出,只限于模塊內(nèi)部使用
-export([init/1, info_log_impl/1]).