这个Erlangsys.config怎么分解呢?

How can this Erlang sys.config be decomposed?

给定一个如下所示的 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 通知的应用程序中都很有用。两者都不应该引用捕鼠器应用程序,因为他们不应该拥有该应用程序的任何 'knowledge'。

编辑:

根据@michael 的指导,我首先在 https://github.com/DonBranson/slack.

将松弛通知发送到单独的 OTP 库

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

话虽如此,因为没有访问控制本身,您可以像这样为不存在的应用程序设置环境:

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

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

你可以做的黑客攻击

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

我不推荐这样做,即使它是可能的,因为如果后来引入了您窃取的名称的应用程序,发布管理器显然不会发现冲突,这显然存在一些危险。

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

另一种方法是 pin_server 申请。

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

图书馆申请

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

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