全局常数是一种反模式吗?[英] Is global constants an anti-pattern?

本文是小编为大家收集整理的关于全局常数是一种反模式吗?的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

我一直认为只是为了持有常数而举办课是一个不好的设计.但是最近,我尝试过谷歌搜索它,并发现以接口为常数是不好的反图案 - 没有提及使用一类常数.

.

我认为,由于一类常数与全球变量并没有太大不同,这就是为什么我反对它并倾向于重构这样的类.它创建了绝对没有上下文的数据类.这些常数最好与实际使用它们的任何东西相关,以赋予它们上下文和含义,并使它们封装在班级中.

别人怎么看?

推荐答案

全球常数不是不好的做法,只要它们是...

  1. ...不变的 - 全局,final/readonly引用可变对象(例如Java ArrayList<T>或C#List<T>)不是一个常数,而是全局状态.
  2. ...需要> 1个类.如果只有一个类需要您的常数,请将常数直接放入班级. (警告:平衡干与Yagni适当.)

bloch涵盖了有效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功能.

是的,被迫创建一种新类型只是为了放置您的常数是有些多余的,但这是我们必须处理的语言中的疣,我们必须处理 - 我们有将我们的常数放在的某个地方,我们最好的选择恰好是不可定力的类.

其他推荐答案

全局常数很好.

全局(非恒定)变量是魔鬼的工作.

其他推荐答案

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

我会说真正的原因全球常数也是有问题的,因此,不再有一个称为myglobals的单身人士,其中包含像myglobals.http_success_ok这样的常数,而是像他们自己的类中的常数一样包装,例如httpstatus.success_ok.

本文地址:https://www.itbaoku.cn/post/627635.html

问题描述

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?

推荐答案

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.

其他推荐答案

Global constants are fine.

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

其他推荐答案

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.