全局常量是反模式吗?

发布于 2024-07-30 15:09:34 字数 237 浏览 5 评论 0原文

我一直认为仅仅为了保持常量而创建一个类是一个糟糕的设计。 但最近,我尝试用谷歌搜索它,发现只有一个接口作为常量是不好的反模式 - 没有提到使用一类常量。

我认为,由于常量类实际上与全局变量没有太大区别,这就是我反对它并倾向于重构此类类的原因。 它创建了一类完全没有上下文的数据。 这些常量最好与实际使用它们的任何东西联系起来,为它们提供上下文和含义,并将它们封装在一个类中。

其他人怎么看?

I've always thought having a class just for the sake of holding constants is a bad design. But recently, I've tried googling for it and found only that having an interface as a constants is bad an anti-pattern - no mention of using a class of constants.

I'm of the opinion that since a class of constants is really not much different from global variables, that's why I'm against it and tend to refactor away such classes. It creates a class of data that has absolutely no context. Those constants are much better off tied to whatever actually use them, to give them context and meaning, as well as making them encapsulated within a class.

What do other people think?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

羁拥 2024-08-06 15:09:35

全局常量没问题。

全局(非常量)变量是魔鬼的杰作。

Global constants are fine.

Global (non-constant) variables are the work of the devil.

北陌 2024-08-06 15:09:35

全局常量并不是坏习惯,只要它们......

  1. 不可变 - 对可变对象(如 Java ArrayList 或 C# List) 不是常量,而是全局状态。
  2. ...>1 类需要。 如果只有一个类需要常量,请将常量直接放在类中。 (警告:适当平衡 DRY 与 YAGNI。)

Bloch 在《Effective Java》中讨论了“常量接口”与“常量类”问题,并提倡“常量类”方法。 您不希望接口中存在常量的原因是它会诱使客户端类“实现”该接口(以便访问常量而不用接口名称作为前缀)。 不过,您不应该这样做 - 该接口实际上并不是对象功能的接口,而是类的外部类型中根深蒂固的编译时便利性。 考虑一下:

interface C { public static final int OMGHAX = 0x539; }
class A implements C { ... }
class B { private A a; }

B 现在不必要地依赖于 C。 如果 A 的实现发生更改,使其不再需要 C 中的常量,则您无法在不破坏的情况下从中删除 implements C它的外部接口 - 某人(可以说是一个非常愚蠢的人,但这样的人比比皆是)可能通过 C 引用来引用 A 对象!

通过将常量放入类中,并使该类不可实例化,您可以告知客户端常量类实际上只是充当子命名空间。 在 C# 中,您将类标记为 static,在 Java 中,您希望将其设为 final 并提供一个无法访问的构造函数:

final class C { 
    private C() { throw new AssertionError("C is uninstantiable"); }
    public static final int OMGHAX = 0x539; 
}

如果您在 Java 中编程并希望常量不带前缀它们带有常量类名,您可以使用import static功能。

是的,仅仅为了有地方放置常量而被迫创建一个新类型有点多余,但这是 Java 和 C# 等语言中我们必须处理的一个问题 - 我们必须将我们的常量放在某个地方,而我们最好的选择恰好是一个不可实例化的类。

Global constants aren't bad practice, as long as they are...

  1. ... immutable - a global, final/readonly reference to a mutable object (like a Java ArrayList<T> or a C# List<T>) is not a constant, but global state.
  2. ... needed by >1 class. If only one class needs your constants, put the constants directly in the class. (Caveat: Balance DRY vs YAGNI appropriately.)

Bloch covers the "constant interface" vs. "constant class" issue in Effective Java, and advocates the "constant class" approach. The reason why you don't want the constants in an interface is that it entices client classes to "implement" that interface (in order to access the constants without prefixing them with the interface name). You shouldn't, though - the interface isn't actually an interface to the object's capabilities, but a compile-time convenience ingrained in the class' external type. Consider this:

interface C { public static final int OMGHAX = 0x539; }
class A implements C { ... }
class B { private A a; }

Class B now unnecessarily has a dependency to C. If the implementation of A changes so that it doesn't need the constants from C, you can't remove implements C from it without breaking its external interface - someone (arguably a very stupid person, but such people abound) might reference an A object through a C reference!

By putting the constants in a class, and by making that class uninstantiable, you inform clients that the constant class really just functions as a sub-namespace. In C# you mark the class as static, in Java you'd want to make it final and give an unreachable constructor:

final class C { 
    private C() { throw new AssertionError("C is uninstantiable"); }
    public static final int OMGHAX = 0x539; 
}

If you program in Java and want the constants without prefixing them with the constant class name, you can use the import static functionality.

And yes, it's slightly redundant to be forced to create a new type just to have somewhere to put your constants, but that's a wart in languages like Java and C# that we have to deal with - we have to put our constants somewhere, and our best option happens to be a non-instantiable class.

无敌元气妹 2024-08-06 15:09:35

全局变量是有问题的,因为它们在模块之间引入了很大程度上不必要的依赖关系。 这些依赖性使得调试问题和重用代码变得更加困难。

我想说,出于同样的原因,真正的全局常量也存在问题,因此,不要使用名为 MyGlobals 的单例,其中包含像 MyGlobals.HTTP_SUCCESS_OK 这样的常量,而是将类似的常量打包在它们自己的类中,例如HttpStatus.SUCCESS_OK。

Global variables are problematic because they introduce largely unnecessary dependencies across modules. These dependencies make it harder to debug problems and reuse code.

I'd say that truly global constants are also problematic for the same reason, So instead of having a singleton called MyGlobals containing a constant like MyGlobals.HTTP_SUCCESS_OK, package like constants together in their own classes, such as HttpStatus.SUCCESS_OK.

简单 2024-08-06 15:09:35

我认为全局变量的问题在于它们创建了全局状态。 全局常量不会这样做,但它们确实负责一些无上下文常量,这可能很糟糕。

如果你需要这样的东西,我建议你创建枚举(如果你有 int 常量)或常量的静态类,这样你就可以给它们一些上下文(例如 Math.PI)

I believe the global variables problem is that they create global state. Global constants don't do this, but they indeed is responsible for some contextless constants, which may be bad.

What I'd suggest if you need stuff like that is create enums (in case you have int constants) or static classes for constants, so you can give them some context (Math.PI, for instance)

旧时浪漫 2024-08-06 15:09:35

我认为没有提及的一件事是更务实的问题。 如果您使用的是编译语言,请记住您必须重新编译才能更改常量的值。 如果您可能想要经常更改它的值,您可能还需要考虑配置文件。

I suppose one thing that's not being mentioned are the more pragmatic issues. If you're using a compiled language, bear in mind that you have to recompile to change the constant's value. If it's a value you may want to change frequently, you may also want to consider a config file.

超可爱的懒熊 2024-08-06 15:09:35

在某些情况下,当全局常量真正保持不变时(不仅对于程序的一次构建而言是恒定的,而且应该在软件产品的整个生命周期及以后),全局常量是完美的方法。

例如,您不希望有多个类,每个类都声明自己的 pi、e 或 HTTP_SUCCESS 常量。

另一方面,如果全局常量是可以更改的任意值(例如由于需求变化),则全局常量可能会产生全局变量的许多问题。 即,如果将这些常量放入配置文件似乎是一个合理的选择,那么它不应该是全局常量。

In some cases, global constants are the perfect way to go when they are truly constant (not only constant for one build of the program, but supposedly during the whole lifespan of the software product and beyond).

For example, you wouldn't want to have several classes each declaring their own constant for pi, e or HTTP_SUCCESS.

On the other hand, global constants can create many of the problems of global variables if they are arbitrary values that could be changed e.g. because of changing requirements. I.e. if putting those constants into a config file seems like a reasonable option, it should not be a global constant.

宁愿没拥抱 2024-08-06 15:09:35

全局变量被广泛认为是一件坏事,通常应该避免。 这就是为什么很多人对单例模式有疑问。 全局变量的问题在于它们是传递性的。

Global variables have been widely recognized as a bad thing and generally should be avoided. This is why so many people have an issue with the Singleton Pattern. The trouble with global variables is that they are transitive.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文