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 Interface is considered good practise in general, is using Interface Constants the only constants that are acceptable to use outside a class context?

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 SOLID PHP? Does it violate any coding principles that are considered Good Practise in PHP? You get the idea …

Note:there is a similar question for Java that 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.

closed as primarily opinion-based by George Stocker♦Feb 19 '14 at 12:46

Many good questions generate some degree of opinion based on expert experience, but answers to this question will tend to be almost entirely based on opinions, rather than facts, references, or specific expertise.
If this question can be reworded to fit the rules in the help center, please edit the question.

Hmm, I'd never come across a need to define constants in an interface before. It's worth knowing that classes implementing the interface can not override the constants, while classes merely extending each other can override constants.
–
CharlesMar 23 '11 at 18:34

I believe constants are not bad since they have predictable values even when we are concerned with unit testability. The global variables are evil since anybody can change it since it is a variable and everything has scope on it but constants will never change its value thus the term constant.
–
Melvin ProtacioFeb 1 '12 at 19:09

2 Answers
2

Well, I think that it boils down to the difference between good and 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:

Now, the reason that I chose those examples is simple. The User interface 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_1 is a decent use-case, since the enum is defined by RFC2616 and will not change for the lifetime of the class.

In general, I don't see the problem with constants and class constants as being a global problem. I see it as a dependency problem. It's a narrow distinction, but a definite one. I see global problems 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 global to be far worse since it's not enforced... Which is why I don't like to lump class dependencies with global dependencies under 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::FOO doesn't introduce any concrete coupling. With that said, I wouldn't introduce an interface just to add a constant to it.

So if you're using interfaces, and you're very sure 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 enough really is acceptable (and it takes an experienced developer to understand the difference), and in those cases it's fine.

What would you suggest as a different pattern for User in this case?
–
JacobMar 24 '11 at 0:35

@Jacob: I would abstract it away. Depending on your needs, I'd likely build an Access class that would get its data from a database table. That way adding a new level is as easy as inserting a new row. Another option would be to build an ENUM class set (where you have one class for each permission role). Then you can extend classes where necessary to provide the appropriate permissions. But there are other methods that will work too
–
ircmaxellMar 24 '11 at 14:05

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" ? )