记录器是否被认为是全局可变状态

时间:2014-12-11 17:36:32

标签: oop logging global-variables

首先让我说“logger”是指负责向用户或程序员报告诊断或进度信息的任何类对象。根据这个定义,“记录器”将包括GUI上的反馈,例如进度条。

我们一再被告知要避免全球状态,尤其是全球可变状态(GMS)。由于记录器本质上是可变的,我最近试图使我的记录器“不是全局的”。我尝试了各种策略(比如通过构造函数注入对记录器的引用)。我终于意识到所有这些方法都只是在口红上涂上口红。

如果记录器有用,则所有类(或至少大多数类)都必须可以访问它。因此它是全球性的。它必须是可变的;记录器的文件无法附加有什么用呢?或者进度条的值不能改变?如果您使记录器成为单例,或者使用依赖注入,或创建静态方法来保存引用,则无关紧要。无论你如何切片,记录器都将成为GMS。

我能做的最好的事情就是创建一个非常小的容器类,它(静态地)创建记录器,并通过静态方法引用该记录器(全局)。

所以最后我的问题。 当我们谈论GMS时,记录器真的是我们担心的吗?你写信给它,但你(几乎)从不读它。记录器真的是GMS吗?

必须静态创建全局记录器,至少在Java中,因此可以通过静态方法访问它。这使得测试很痛苦。但是我们能做些什么呢?

1 个答案:

答案 0 :(得分:1)

简答:从技术上讲,您描述的记录器是GMS,但不是,当我们谈论GMS时,它们并不是我们所担心的。原因是它们本质上是只写,因此状态不会影响程序其余部分的任何内容。当然,你必须确保它们实际上是只写的,尽可能合理(即通常可以不担心你的文件记录器填满了文件系统;它不会没有问题。问它到目前为止记录了多少行。

关于你的测试问题:记录器本身当然可以是一个普通的类,可以自己测试。其他代码与记录器的唯一全局实例的交互是一种难以测试的问题,因此通常最好只使这些代码完全最小和简单,并使它们不经过测试。

如果你真的想测试它们,一个务实的解决方案是给那个容器类setInstance以及getInstance。在这种情况下,最好使默认的类实例化记录器实际上是一个无操作的记录器,并让主应用程序通过setInstance初始化真实的生产记录器。

理论华夫饼干:" Global"字面意思只是意味着它可以从任何地方访问(全局访问)。它通常也意味着它只有一个(全局,如小写单例)。通常由这两个问题引起的问题是:

  1. 当您的代码依赖于全局
  2. 时,来自呼叫网站的情况并不明显
  3. 如果是可变的,它允许系统的任何两个部分之间隐藏的交互
  4. 很难使用替代实例 - 通常是测试问题,但有时也会对生产代码感到头痛。
  5. 通常,在(全球!)类中包装某些东西并不会使它变得不那么全局 - 它仍然可以被任何人访问,并且默认情况下会出现这种情况。仍然只有一个。唯一的优势在于,特别是在Java中,它使代码看起来更加自律,并传达了您对此问题的看法。

    可以解决全球单身人士的问题,例如:与工厂模式类似,但对于可能预生成的对象,这将解决替代实例问题。

    全球访问问题是AFAICT无法解决的问题,但可以通过对谁获得访问权限(使对象不完全全局)的更精细控制来减轻这些问题,将实例传递给每个可能的构造函数(或方法调用),手动或通过一些依赖注入库。手动解决方案当然是对于样板代码; DI libs具有学习曲线,与普通全局变量相比仍然是非零样板。

    特别是对于记录器的描述,#1被视为一个可接受的假设,即字面上每一段代码都可能记录一些东西; #2由记录器解决,保证尽管可变,但它无法让其他代码隐蔽地或偶然地相互影响;和#3可以通过setInstance这个东西来解决,一个非常简单的"" Factory-oid解决方案的变体。