php 接口常量的优缺点

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5350672/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 21:07:06  来源:igfitidea点击:

Pros and Cons of Interface constants

phpinterfaceconstants

提问by Gordon

PHP interfaces allow the definition of constants in an interface, e.g.

PHP 接口允许在接口中定义常量,例如

interface FooBar
{
    const FOO = 1;
    const BAR = 2;
}
echo FooBar::FOO; // 1

Any implementing class will automatically have these constants available, e.g.

任何实现类都会自动提供这些常量,例如

class MyFooBar implement FooBar
{
}
echo MyFooBar::FOO; // 1

My own take on this is that anything Global is Evil. But I wonder if the same applies to Interface Constants. Given that Coding against an Interfaceis considered good practise in general, is using Interface Constants the only constants that are acceptable to use outside a class context?

我自己的看法是,任何 Global 都是邪恶的。但我想知道这是否同样适用于接口常量。鉴于对接口进行编码通常被认为是好的做法,使用接口常量是唯一可以在类上下文之外使用的常量吗?

While I am curious to hear your personal opinion and whether you use Interface constants or not, I'm mainly looking for objective reasons in your answers. I dont want this to be a Poll Type question. I'm interested in what effect using interface constants has on Maintainability. Coupling. Or Unit Testing. How does it relate to SOLIDPHP? Does it violate any coding principles that are considered Good Practise in PHP? You get the idea …

虽然我很想听听您的个人意见以及您是否使用接口常量,但我主要是在您的答案中寻找客观原因。我不希望这是一个民意调查类型的问题。我对使用接口常量对可维护性的影响很感兴趣。耦合。或单元测试。它与SOLIDPHP 有什么关系?它是否违反了 PHP 中被认为是良好实践的任何编码原则?你明白了……

Note:there is a similar question for Javathat listed some quite good reasons why they are Bad Practice, but since Java isn't PHP, I felt it justified to ask it within the PHP tag again.

注意:Java有一个类似的问题,列出了一些很好的原因,为什么它们是不好的做法,但由于 Java 不是 PHP,我觉得再次在 PHP 标签中询问它是合理的。

回答by ircmaxell

Well, I think that it boils down to the difference between goodand good enough.

好吧,我认为这归结为足够好之间的区别。

While in most cases you can avoid the use of constants by implementing other patterns (strategy or perhaps flyweight), there is something to be said for not needing a half dozen other classes to represent a concept. I think what it boils down to, is how likely is there a need for other constants. In other words, is there a need to extend the ENUM provided by the constants on the interface. If you can foresee needing to expand it, then go with a more formal pattern. If not, then it may suffice (it'll be good enough, and hence be less code to write and test). Here's an example of a good enough and a bad use:

虽然在大多数情况下,您可以通过实现其他模式(策略或可能是享元)来避免使用常量,但对于不需要六个其他类来表示一个概念,还是有话要说的。我认为它归结为,需要其他常量的可能性有多大。换句话说,是否需要扩展接口上的常量提供的ENUM。如果您可以预见需要扩展它,那么请使用更正式的模式。如果没有,那么它可能就足够了(它会足够好,因此编写和测试的代码更少)。这是一个足够好的和不好的用法的例子:

Bad:

坏的:

interface User {
    const TYPE_ADMINISTRATOR = 1;
    const TYPE_USER          = 2;
    const TYPE_GUEST         = 3;
}

Good Enough:

够好了:

interface HTTPRequest_1_1 {
    const TYPE_CONNECT = 'connect';
    const TYPE_DELETE  = 'delete';
    const TYPE_GET     = 'get';
    const TYPE_HEAD    = 'head';
    const TYPE_OPTIONS = 'options';
    const TYPE_POST    = 'post';
    const TYPE_PUT     = 'put';

    public function getType();
}

Now, the reason that I chose those examples is simple. The Userinterface is defining an enum of user types. This is very likely to expand over time and would be better suited by another pattern. But the HTTPRequest_1_1is a decent use-case, since the enum is defined by RFC2616 and will not change for the lifetime of the class.

现在,我选择这些示例的原因很简单。该User接口正在定义用户类型的枚举。这很可能会随着时间的推移而扩展,并且会更适合另一种模式。但这HTTPRequest_1_1是一个不错的用例,因为枚举是由 RFC2616 定义的,并且在类的生命周期内不会改变。

In general, I don't see the problem with constants and class constants as being a globalproblem. I see it as a dependency problem. It's a narrow distinction, but a definite one. I see globalproblems as in global variables which are not enforced, and as such create a soft global dependency. But a hard-coded class creates an enforced dependency, and as such create a hard global dependency. So both are dependencies. But I consider the globalto be far worse since it's not enforced... Which is why I don't like to lump class dependencieswith global dependenciesunder the same banner...

一般来说,我不认为常量和类常量的问题是一个全局问题。我认为这是一个依赖问题。这是一种狭隘的区别,但却是明确的区别。我将全局问题视为未强制执行的全局变量,因此会创建软全局依赖项。但是一个硬编码的类会创建一个强制依赖,并因此创建一个硬全局依赖。所以两者都是依赖。但我认为全局要糟糕得多,因为它没有强制执行......这就是为什么我不喜欢将类依赖全局依赖放在同一旗帜下......

If you write MyClass::FOO, you're hard-coded to the implementation details of MyClass. This creates a hard-coupling, which makes your code less flexible, and as such should be avoided. However, interfaces exist to permit exactly this type of coupling. Therefore MyInterface::FOOdoesn't introduce any concrete coupling. With that said, I wouldn't introduce an interface just to add a constant to it.

如果您编写MyClass::FOO,您将被硬编码到MyClass. 这会产生硬耦合,这会降低您的代码的灵活性,因此应该避免这种情况。然而,接口的存在正好允许这种类型的耦合。因此MyInterface::FOO不介绍任何具体的耦合。话虽如此,我不会仅仅为了向其添加常量而引入接口。

So if you're using interfaces, and you're verysure that you (or anyone else for that matter) won't need additional values, then I don't really see a huge issue with the interface constants... The best designs wouldn't include any constants or conditionals or magic-numbers or magic-strings or hard-coded anything. However, that adds additional time to the development, as you must consider the uses. My view is that most times it's absolutely worth taking the additional time to build a great solid design. But there are times when good enoughreally is acceptable (and it takes an experienced developer to understand the difference), and in those cases it's fine.

因此,如果您正在使用接口,并且您非常确定您(或其他任何人)不需要额外的值,那么我真的没有看到接口常量的大问题......最好的设计不包括任何常量或条件或幻数或幻字符串或硬编码的任何东西。但是,这会增加开发时间,因为您必须考虑用途。我的观点是,在大多数情况下,花额外的时间来构建一个伟大的实体设计是绝对值得的。但是有时候足够好确实是可以接受的(并且需要有经验的开发人员才能理解差异),在这些情况下它很好。

Again, that's just my view on it...

再说一遍,这只是我对它的看法......

回答by umlcat

I think that its usually better to handle constants, specially enumerated constants, as a separate type ("class") from your interface:

我认为将常量(特别是枚举常量)作为与界面分开的类型(“类”)处理通常更好:

define(TYPE_CONNECT, 'connect');
define(TYPE_DELETE , 'delete');
define(TYPE_GET    , 'get');
define(TYPE_HEAD   , 'head');
define(TYPE_OPTIONS, 'options');
define(TYPE_POST   , 'post');
define(TYPE_PUT    , 'put');

interface IFoo
{
  function /* int */ readSomething();
  function /* void */ ExecuteSomething(/* int */ param);
}

class CBar implements IFoo
{
  function /* int */ readSomething() { ...}
  function /* void */ ExecuteSomething(/* int */ param) { ... }
}

or, if you want to use a class as a namespace:

或者,如果你想使用一个类作为命名空间:

class TypeHTTP_Enums
{
  const TYPE_CONNECT = 'connect';
  const TYPE_DELETE  = 'delete';
  const TYPE_GET     = 'get';
  const TYPE_HEAD    = 'head';
  const TYPE_OPTIONS = 'options';
  const TYPE_POST    = 'post';
  const TYPE_PUT     = 'put';
}

interface IFoo
{
  function /* int */ readSomething();
  function /* void */ ExecuteSomething(/* int */ param);
}

class CBar implements IFoo
{
  function /* int */ readSomething() { ...}
  function /* void */ ExecuteSomething(/* int */ param) { ... }
}

Its not that you are using just constants, you are using the concept of enumerated values or enumerations, which a set of restricted values, are considered a specific type, with a specific usage ("domain" ? )

这并不是说您仅使用常量,而是使用枚举值或枚举的概念,其中一组受限值被视为特定类型,具有特定用法(“域”?)