给出一个如下所示的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图书馆发布松弛通知。
答案 0 :(得分:2)
由于Erlang不以任何方式控制节点内应用程序和环境之间的访问(任何应用程序都可以访问任何其他应用程序环境),我不确定通过这种微妙的使用改变你真正获得了什么......事实上,如果pin_server明确地并且绝对是捕鼠器应用程序的一部分是合乎逻辑的,我认为你应该不尝试这样做;使用系统,因为它应该被用来代替。
虽然这样说,因为没有这样的访问控制,你可以为不存在的应用程序设置环境:
application:set_env(nonexisting, foo, bar).
application:set_env(anotherphantom, bat, baz).
但是如果在sys.config中运行一个包含非现有应用程序的节点,则不会加载这些应用程序的配置。
在启动顶级主管之前,您可以让您的应用程序开始阅读您的环境并设置不太真实的pin_server应用程序的环境,并从捕鼠器应用程序中取消设置环境。这将实现你想要的,但是......
虽然有可能,但我不建议这样做,因为如果稍后会引入你所掠夺的名称的申请,发布经理显然会发现冲突。
另一种方法是将pin_server设为应用程序。
如果唯一的障碍是建议的pin_server应用程序根本没有任何意义,除非在您的捕鼠器应用程序的上下文中,那么您可以将其设为“包含的应用程序”。包含的应用程序是具有自己的应用程序文件的应用程序,并且实际上就像普通(主要)应用程序一样,但它们是在主应用程序的监督树中启动的(请参阅Included Applications)并立即允许您进行更改如果您不介意创建额外的应用程序,请使用。
同样它是一个应用程序,我不认为这可能适合你的情况,但是,还有一个'库应用程序',这是一个没有服务器的应用程序(你不需要实现应用程序回调模块,它只是成为模块,API和环境的逻辑分组。如果您创建没有mod
条目的应用程序文件,它将成为库应用程序。我认为它不合适的原因是pin_server
听起来像服务器,因此应该受到监督,但这也可以让你改变你想要的用途。
答案 1 :(得分:0)
我看到的最佳解决方案是要求使用equals()
和pin_server
的任何应用读取环境变量,并在初始化时将它们注入这些组件。