簡體   English   中英

我怎樣才能擁有一個“私人” Erlang 模塊?

[英]How can I have a "private" Erlang module?

我更喜歡使用長度少於 1000 行的文件,因此我正在考慮將一些 Erlang 模塊分解成更小的部分。

有沒有辦法在不擴展我圖書館的公共 API 的情況下做到這一點?

我的意思是,只要有模塊,任何用戶都可以執行module:func_exported_from_the_module 據我所知,真正讓某些東西成為私有的唯一方法是不從任何模塊中導出它(即使那樣也可以戳洞)。

因此,如果在技術上沒有辦法完成我正在尋找的東西,是否有約定? 例如,Python類中沒有私有方法,但約定是在_my_private_method中使用前導_來標記為私有。

我承認答案可能是“不,你必須有 4K LOC 文件。”

最接近約定的是使用 edoc 標記,如@private@hidden

文檔

@hidden

標記 function,這樣它就不會出現在文檔中(即使生成了“私有”文檔)。 用於調試/測試功能等。內容可作為注釋; 它被 EDoc 忽略。

@private

將 function 標記為私有(即,不是公共接口的一部分),這樣它就不會出現在正常的文檔中。 (如果生成“私有”文檔,則將包含 function。)僅對導出函數有用,例如 spawn 的入口點。 (非導出函數始終是“私有的”。)內容可以用作注釋; 它被 EDoc 忽略。

請注意,這個答案開始於對@legoscia 的回答的評論

目前不支持不同方法的不同可見性。

當前的約定,如果你想那樣稱呼它,是有一個(或幾個)'facade' my_lib.erl模塊導出你的庫/應用程序的公共 API。 調用庫的任何內部模塊都是在玩火,應該避免(調用它們需要您自擔風險)。

BEAM VM 中有一些非常好的功能依賴於能夠從任何模塊調用導出的函數,例如

  1. Callbacks (funs/anonymous funs), MFA, erlang:apply/3 :調用代碼不需要了解庫的任何信息,只需要調用它即可
  2. gen_server等行為需要前面的點才能起作用
  3. 熱重載:您可以在不停止 VM 的情況下升級任何模塊的字節碼。 VM 內的代碼服務器最多為任何模塊維護兩個版本的字節碼,將外部調用(那些帶有Module:的)重定向到最新版本,並將內部調用重定向到當前版本。 這就是為什么您可能會在長時間運行的服務器中看到一些?MODULE:調用,以便能夠升級代碼

您可能會爭辯說,這些點可用於更細粒度的面向 BEAM 的可見性級別,這是真的。 但我認為它不會解決外觀模塊無法解決的任何問題,並且會使 VM/代碼的其他部分變得非常復雜。

獎金

類似的情況適用於記錄不透明類型,記錄僅在編譯時存在,而不透明類型僅在透析器時存在。 沒有什么能阻止你在任何地方訪問它們的內部結構,但如果你這樣 go ,你只會發現問題:

  • 你在記錄中插入一個新字段,突然,你所有的{record_name,...} = break
  • 您使用一個返回opaque_adt()的庫,您知道它是一個列表並像這樣使用。 庫升級為包含列表的大小,所以現在opaque_adt()是一個tuple()並且隨之而來的是混亂

只有那些在-export屬性中指定的函數對其他模塊可見,即“公共”函數。 所有其他功能都是私有的。 如果您只指定了-compile(export_all) ,那么模塊中的所有函數在外部都是可見的。 不建議使用-compile(export_all)

我不知道 Erlang 有任何現有約定,但為什么不采用 Python 約定? 假設“庫私有”函數以下划線為前綴。 你需要用單引號引用 function 名稱才能工作:

-module(bar).

-export(['_my_private_function'/0]).

'_my_private_function'() ->
    foo.

然后你可以稱它為:

> bar:'_my_private_function'().
foo

對我來說,這清楚地表明我不應該調用 function,除非我知道自己在做什么。 (甚至可能不會)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM