当前位置: 首页 > 知识库问答 >
问题:

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

戚宏浚
2023-03-14

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

我们一再被告知要避免全局状态,尤其是全局可变状态(GMS)。因为伐木者天生是可变的,所以我最近试图让我的伐木者“不是全球性的”。我尝试了各种策略(比如通过构造函数向记录器注入引用)。我终于意识到,所有的方法都是把口红贴在猪身上。

日志记录器必须是所有类(或至少大多数类)都可以访问的,如果它是有用的。因此,它是全球性的。而且它必须是可变的;一个不能附加文档的记录器有什么好处?或者进度条的值不能改变?无论您是将记录器设置为单例记录器,还是使用依赖项注入,或者创建静态方法来保存引用,都没关系。不管你怎么切片,记录器都是GMS。

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

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

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

共有1个答案

姜俊友
2023-03-14

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

至于你的测试问题:记录器本身当然可以是一个普通的类,它可以自己进行测试。其他代码与记录器的唯一全局实例的交互很难测试,所以通常最好让这些代码位绝对最小化和简单明了,并且让它们未经测试。

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

理论胡言乱语:“全球”字面上的意思是它可以从任何地方访问(全球访问)。它通常还意味着它只有一个(全局的,如小写的s单例)。这两个问题通常会引起以下问题:

  1. 当你的代码依赖于全局
  2. 如果可变,它允许系统的任何两个部分之间的隐藏交互
  3. 很难使用替代实例--通常是测试问题,但有时也对生产代码感到头疼。

一般来说,将某物包装在(全局!)类并没有降低它的全球性——它仍然可以被任何人访问,默认情况下仍然只有一个。唯一的一点好处是,Java具体来说,它使代码看起来更有纪律性,并传达了您对这个问题的想法。

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

全局as-in-access问题是无法解决的,但可以通过对谁获得访问权(使对象不完全是全局的)进行更细粒度的控制来缓解这些问题,方法是手动或通过某种依赖项注入库将实例传递到每个可能的构造函数(或方法调用)中。当然,手动解决方案会产生样板代码;DI库有一条学习曲线,与普通全局库相比仍然是非零样板。

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

 类似资料:
  • 这是我写的一个脚本的摘录: 我的一个同事说,这里使用全局变量是不好的。 我可以看出这有多么不方便,因为我必须先使用,然后才能将其递增1。 但是为什么使用全局被认为是糟糕的编程呢? 如果这是一个非常明显的问题,我很抱歉,我对Python相对陌生,并试图尽可能多地理解事物。

  • 编译器必须为constexpr的不同路径生成多个函数,这取决于函数的调用方式。所以也许它在使用过载分辨率。 被接受的建议没有提到“sfinae”或“过载分辨率”。 所以我很好奇这两个概念是否适用于“constexpr if”。

  • 我使用springdoc openapi for java SpringBoot RESTful应用程序定义了以下: 是否可以将其全局应用于所有路径,而不必在代码中的任何地方添加注释到注释? 如果是,如何添加排除到不安全的路径?

  • 然而,我不确定我是否理解他的观点,因为根据我的理解,当我们有一个父类引用变量指向子类对象时,一个行为被认为是多态的(侧重于动态多态性)。 然后在运行时获取父类变量所指向的实际对象,并调用其方法,如这里所解释的那样。 但是,我没有在我的项目中使用上向转换(即用对象类变量初始化POJO类)。 因此,我的问题是--尽管父类(对象)从未用作引用变量,但重写toString()是否被视为多态性? 我在Sta

  • 问题内容: 是否应该将记录器声明为静态?通常,我已经看到记录器的两种类型的声明: 要么 应该使用哪一个?两者的优缺点是什么? 问题答案: 非静态形式的优点是,您可以像下面的(抽象)基类中声明它,而不必担心会使用正确的类名: 但是,其缺点显然是将为该类的每个实例创建一个全新的记录器实例。这本身可能并不昂贵,但会增加大量开销。如果您想避免这种情况,请改用表格。但是它的缺点是,您必须在每个单独的类中声明

  • 我有一个父组件,它有许多子组件(子组件是一个带有彩色背景的空div)。 我想改变孩子的颜色,但要确保我正在使它变成一个不同的颜色比它已经是-例如,如果孩子是蓝色的,我想改变它到另一个颜色,不是蓝色。 为此,我使用一个道具来设置初始颜色,并将此道具保存到孩子的状态。 当我点击div更改颜色时,我想访问div的当前颜色,以便我可以将其从选择中排除,当然可以从中进行选择 1)这被认为是可以做的反应吗?2