1

给定一个看起来像这样的 Erlang sys.config :

[
    {mousetrap, [
        {slack_user, "mousetrap"},
        {slack_channel, "#mousetrap"},
        {slack_token, "<slack token here>"},
        {pins_export_file, "/sys/class/gpio/export"},
        {pins_root_directory, "/sys/class/gpio/gpio"},
        {pins, [
                {gpio0, 30, "1 (over workshop door)"},
                {gpio0, 31, "2 (by basement freezer)"},
                {gpio1, 16, "3 (in the kitchen pantry)"},
                {gpio0, 5, "4 (Not yet wired)"}
        ]},
        {quiet_minutes, 5},
        {pin_check_interval_seconds, 1}
    ]}
].

我想把它分开,以便每个组件的设置在配置文件中分开。例如,BeagleBone 的 pin_library 确实没有理由包含整个捕鼠器应用程序的知识,因此将其分解是有意义的。对于向 Slack 发送消息的 notification_library 也是如此:

[
    {mousetrap, [
        {pins, [
                {gpio0, 30, "1 (over workshop door)"},
                {gpio0, 31, "2 (by basement freezer)"},
                {gpio1, 16, "3 (in the kitchen pantry)"},
                {gpio0, 5, "4 (Not yet wired)"}
        ]},
        {quiet_minutes, 5}
    ]},
    {pin_server, [
        {pins_export_file, "/sys/class/gpio/export"},
        {pins_root_directory, "/sys/class/gpio/gpio"},
        {pin_check_interval_seconds, 1}
    ]},
    {notification_library, [
        {slack_user, "mousetrap"},
        {slack_channel, "#mousetrap"},
        {slack_token, "<slack token here>"}
    ]}
].

但是,这不起作用,因为 pin_server 和 notification_library 不是应用程序,这是此构造在 sys.config 中所需要的。将这些设置分解为合适的类别的正确 Erlang 方法是什么,以便pin_library.erl可以改变使用:

{ok, PinsRootDirectory} = application:get_env(mousetrap, pins_root_directory),

使用

{ok, PinsRootDirectory} = application:get_env(pin_server, pins_root_directory),

编辑:

只是为了澄清为什么我认为这很重要。组件 pin_server 和 notification_library 尝试遵守SRP。但是当 pin_server 调用时application:get_env(mousetrap, pins_root_directory),它打破了 SRP 的墙,因为它在不应该有依赖关系的组件上创建了依赖关系。也就是说,在捕鼠器应用程序上。现在它不能在不更改代码的情况下在其他应用程序中重复使用。notification_library 也是如此。pin_server 可能适用于任何想要询问 BBB 引脚的应用程序。notification_library 在任何想要发送 Slack 通知的应用程序中都很有用。两者都不应该引用捕鼠器应用程序,因为他们不应该对该应用程序有任何“知识”。

编辑:

根据@michael 的指导,我首先在https://github.com/DonBranson/slack向单独的 OTP 库发出 slack 通知。

4

2 回答 2

3

由于 Erlang 不以任何方式控制节点内的应用程序和环境之间的访问(任何应用程序都可以访问任何其他应用程序环境),我不确定您从这种微妙的使用变化中真正获得了什么......事实上,如果 pin_server 显然是mousetrap应用程序的一部分是合乎逻辑的,我认为你不应该尝试这样做;使用系统,因为它应该被使用。

尽管如此,由于没有访问控制,您可以为不存在的应用程序设置环境,如下所示:

application:set_env(nonexisting, foo, bar).
application:set_env(anotherphantom, bat, baz).

但是,如果您在 sys.config 中运行具有不存在应用程序的节点,则不会加载这些应用程序的配置。

你可以做的一个黑客

在启动顶级主管之前,您可以让您的应用程序开始读取您的环境并设置不存在的 pin_server 应用程序的环境,并从 mousetrap 应用程序中取消设置环境。这将实现您想要的,但是...

尽管有可能,但我不建议这样做,因为如果稍后引入您盗用的名称的应用程序,发布管理器显然不会发现冲突。

更好的选择(应用程序和包含的应用程序)

另一种方法是使 pin_server 成为应用程序。

如果唯一的障碍是建议的 pin_server 应用程序除了在捕鼠器应用程序的上下文中之外根本没有任何意义,那么您可以将其设为“包含的应用程序”。包含的应用程序是具有自己的应用程序文件的应用程序,实际上就像普通(主要)应用程序一样,但它们是在您的主要应用程序的监督树中启动的(请参阅包含的应用程序),并且会立即允许您更改使用想要,如果您不介意创建额外的应用程序。

图书馆应用

同样,它是一个应用程序,我认为这可能不适合您的情况,但是,还有“库应用程序”之类的东西,它是一个没有服务器的应用程序(您不需要实现该应用程序回调模块,它只是成为您的模块、API 和环境的逻辑分组)。如果您创建一个没有mod条目的应用程序文件,它将成为一个库应用程序。我认为它可能不合适的原因是它pin_server听起来像一个服务器,因此应该受到监督,但这也可以让你改变你想要的用途。

于 2015-11-07T13:24:19.387 回答
0

我看到的最佳解决方案是要求任何使用pin_servernotification_library读取环境变量的应用程序,并在初始化时将它们注入这些组件。

于 2015-11-07T15:21:20.000 回答