2014-09-18 52 views
1

Erlang類型規範是否屬於.hrl文件(它們被加載到任何需要它們的.erl文件中),還是應該保存在Erlang模塊中,然後導出(這將允許它們在其他模塊中使用)?在我看來,這兩種方法都可以達到同樣的效果。類型規範是否屬於.hrl文件?

  • 我錯過了什麼細微差別? (我知道頭文件的內容被複制到每個使用它們的文件中,實質上是在編譯時複製代碼)。
  • 是否有時候應該使用一種方法而不是另一種方法?

在此先感謝!

回答

2

它確實重要的一點是,規範實際上用於通過edoc應用程序生成函數/模塊的文檔。

如果正確的spec子句不在正確的函數子句之上,edoc將會抱怨並且整個模塊的文檔生成將失敗。

請想想edoc。

1

這並不重要。你可以把它們放在合理的地方。

  • 如果您的類型與記錄定義密切相關,並且應該知道其內部結構 - 將它們放入.hrl文件中。
  • 如果您不想公開內部結構(例如,您使用了proplists,但您希望將來更改爲字典),最好使用accessor函數創建模塊,並在其中添加註釋:「不依賴於這種類型的內部結構」。你仍然想導出它,以確保其他模塊使用它。即使他們將它用作黑盒子。

如果你在.hrl中放置了某些東西,而其他模塊依賴於它 - 它很難改變。當你把它放在模塊中時,應該更容易修改和重構。

3

類型規範(即-spec屬性)屬於定義函數的模塊。期。

另一方面,類型定義(-type,-opaque)可以在.hrl文件中定義,但我認爲這通常是一個糟糕的決定。這意味着,包括標題在內的每個模塊都將在本地「定義」類型。這可能會導致名稱空間衝突,當模塊已經定義了一個類型,該類型也在您希望包含的頭文件中定義。 從模塊中導出類型而不是在.hrl中定義它們將爲您提供名稱空間前綴,並在本地定義的類型(mytype())和外部應用程序/模塊(yourmod:yourtype()或sic !, yourmod:mytype())之間定義類型。

通常,在編寫Erlang應用程序或庫時,最好在使用它的模塊中定義類型(最多)。對於導出到庫之外的類型,從主庫模塊導出它們 - 如果應用程序名爲myapp,則使所有公共類型可訪問,如myapp:config(),myapp:some_record()

還有一件事讓我想起來:透析器不喜歡裸露的記錄定義 - 建議明確定義記錄類型(因此每個-record一個-type)。另一方面,將記錄定義放置在頭文件中很方便,因此它們可以在不同地方的代碼之間共享(如src/mymod.erltest/mymod_tests.erl)。在這種情況下,我會在頭文件中定義記錄(src/mymod.hrl爲私有模塊,如果模塊是應用程序/庫公共接口的一部分,則爲include/mymod.hrl),但仍定義並從其所屬模塊中導出類型(即mymod:some_record())。

提出的點tkowal也很重要。如果你不想公開內部結構,那麼-opaque屬性就是爲了做到這一點 - 它說「不依賴於這種類型的內部結構」。所以你只需要用-opaque而不是-type來定義一個類型,導出它,讓Dialyzer在代碼中的每一個地方警告你,這些地方意外地建立了一個這種類型的術語,但沒有明確說明它,或者說每個匹配哪個模式試圖在定義類型的模塊之外解構該類型。

+0

友善提醒所有初學者:如果你想像myapp:mytype()那樣使用它,請不要忘記導出你的類型。 – 2017-08-11 16:37:07