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



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

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

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

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

所以终于到了我的问题。当我们谈论GMS时,记录器真的是我们担心的吗? 你写信给它,但你(几乎(从未读过它。 记录器真的是 GMS 吗?

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

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

至于你的测试问题:记录器本身当然可以是一个普通的类,可以自己进行测试。其他代码与记录器的唯一全局实例的交互测试起来很痛苦,因此通常最好只使这些代码位绝对最小和直接,并将它们保留为未经测试。

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

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

  1. 当您的代码依赖于全局时,从调用站点中看不出来
  2. 如果可变,则允许系统的任何两个部分之间进行隐藏的交互
  3. 很难
  4. 使用替代实例 - 通常是一个测试问题,但有时也是生产代码的头痛问题。

一般来说,将某些东西包装在一个(全局!(类中并不会降低它的全局性 - 任何人都可以访问它,默认情况下仍然只有一个。 唯一的优势是,特别是在Java中,它使代码看起来更有纪律,并传达了你已经考虑过这个问题的信息。

全局

作为单例的事情可以解决,例如,使用类似于工厂模式的东西,但对于可能预先生成的对象,这将解决替代实例问题。

全局即访问问题是 AFAICT 无法解决的,但它们可以通过对谁获得访问权限的更细粒度控制(使对象不完全全局(来缓解,方法是将实例传递到每个可能的构造函数(或方法调用(,无论是手动还是通过一些依赖注入库。手动解决方案当然会产生样板代码;与普通全局变量相比,DI 库具有学习曲线,并且仍然是非零样板。

特别是在你描述的记录器的情况下,#1 被认为是一个可接受的假设,即从字面上看,每段代码都可能记录一些东西; #2 由记录器解决,保证虽然可变,但它不能让其他代码片段秘密或意外地相互影响; #3 可以通过例如setInstance的事情来解决, 工厂类解决方案的一个非常"精简"的变体。

最新更新