在我的大多数模块中,我
require Logger
然后做一些日志记录。在我不熟悉的模块中,我经常进行更改,包括添加一些日志记录,然后我必须使用记录器标记我。
每个模块中require
记录器的成本是多少?有没有一种干净的方法可以永远require
Logger而不在每个模块中提及它?
答案 0 :(得分:7)
require
的主要目的是提供对所需模块中声明的宏的访问权限:
模块中的公共功能是全局可用的,但是为了使用宏,您需要通过要求定义它们的模块来选择加入。
的文档
- 来自Kernel.SpecialForms.require/2
此外,来自Elixir guide:
宏是词汇:无法全局注入代码或宏。要使用宏,您需要明确要求或导入定义宏的模块。
重点是我的。这样做是为了您自己的安全:与函数不同,宏可能会彻底修改您现有的AST。 Logger
是此行为的一个完美示例:当级别小于config中指定的相应compile_time_purge_level
时,它不会在AST中留下任何痕迹。没有单一的noop。没有。虚无。
这就是为什么Logger
被实现为宏的原因。
有两种方法可以克服这种行为。
<强> 1。简单。不推荐。
将Logger
作为一个函数:
defmodule Log do
require Logger
def log(whatever), do: Logger.log(whatever)
end
Log.log
现在随处可用(因为它是功能。)
缺点:
noop
级别的代码中会留下Log.log
次debug
次来电。这可能会影响表现。Logger
必须是宏的另一个原因)将变得无用 - 你无法获取日志行的行号,模块等因为它们将永远给宏观调用的网站(信用@NathanielWaisbrot)<强> 2。正确。推荐使用。强>
创建自己的MyApp.Utils
模块,但在每个项目中都存在比todo-or-tictactoe-exercise略复杂的模块。在此模块中,保存所有实用程序功能等,实现宏回调__using__
:
defmodule MyApp.Utils do
defmacro __using__(opts \\ []) do
quote do
require Logger
require MyApp.Utils # if this module has macros itself
def helper, do: Logger.log("Hey, I am always included")
...
end
...
end
end
是的,现在在使用Logger
的所有模块中,您必须明确use MyApp.Utils
,但由于它包含在应用程序范围内使用的方便帮助程序,因此Logger
本身是必需的。免费。
答案 1 :(得分:0)
模块不会从&#34; base&#34;继承。模块。没有继承权。将每个模块视为一个独立的工作单元。
因此,每个模块都应该导入它完成工作所需的所有依赖项。因此,需要在需要进行日志记录的模块中使用Logger是明确的。