把記錄作為主要的數據結構。記錄是Erlang 4.3 時才引入的一種帶標記的元組(參看 EPK/NP 95:034)。它類似于 C 語言中的 struct 或 Pascal 中的 record。
如果記錄將用于多個模塊,它的定義應放在這些模塊所包括的一個頭文件中(帶有 .hrl 后綴)。如果記錄只用在一個模塊中,則它的定義應位于定義模塊的文件的最前面位置處。
Erlang 的記錄特性可以保證數據結構跨模塊的一致性,因此在模塊間傳遞數據結構時,接口函數應使用記錄。
使用記錄特性所提供的選擇器(selector)和構造函數(constructor)來管理記錄實例。不要使用明顯假定記錄是一個元組的匹配。范例如下:
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. % 不要這樣做
使用帶標記的返回值。
不要像下面這樣編程:
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千萬不要在搞不清用法的情況下使用 catch 和 throw!要盡可能少地使用它們。
復雜與非信任輸入(從外部環(huán)境中所輸入的內容,而非來自于可信的程序時)可能會導致代碼很多深層次位置的錯誤,當程序處理這些類型的輸入時,catch 與 throw 就顯得非常有用了。關于這一點,典型的例子就是編譯器。
千萬不要在搞不清用法的情況下使用 get 和 put 等函數!盡量少用它們。
引入一個新的參數,就可以重寫使用進程字典的函數。
范例如下:
不要像下面這樣編程:
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 會容易導致,在同樣輸入下函數的結果卻隨情況不同而改變。這使得代碼難以閱讀,因為代碼已經失去了確定性。調試也變得很復雜,因為使用 get 和 put 的函數不僅是自身參數的函數,而且還是進程字典的函數。Erlang 中的很多運行時錯誤(比如 bad_match)就包括函數的參數,但從來不包括進程字典。
不要使用 -import,使用它會讓代碼變得難以閱讀,這是因為無法弄清函數定義所在的模塊。使用 exref(交叉引用工具)查找模塊依賴。
一定要搞清楚某個函數之所以導出的原因。這種原因可能包括以下幾種:
apply、spawn 調用,但只限于本模塊內部調用。 使用不同的 -export 進行分組,并相應對它們進行注釋。范例如下:
%% 用戶接口
-export([help/0, start/0, stop/0, info/1]).
%% 模塊間導出
-export([make_pid/1, make_pid/3]).
-export([process_abbrevs/0, print_info/5]).
%% 導出,只限于模塊內部使用
-export([init/1, info_log_impl/1]).