php - clases - trait interface
Pros y contras de las constantes de la interfaz (2)
Bueno, creo que se reduce a la diferencia entre lo bueno y lo suficientemente bueno .
Si bien en la mayoría de los casos puede evitar el uso de constantes mediante la implementación de otros patrones (estrategia o quizás flyweight), hay algo que decir para no necesitar media docena de otras clases para representar un concepto. Creo que se reduce a qué tan probable es la necesidad de otras constantes. En otras palabras, ¿existe la necesidad de extender el ENUM provisto por las constantes en la interfaz? Si puede prever que necesita expandirlo, entonces vaya con un patrón más formal. De lo contrario, puede ser suficiente (será lo suficientemente bueno y, por lo tanto, tendrá menos código para escribir y probar). Aquí hay un ejemplo de un buen uso y un mal uso:
Malo:
interface User {
const TYPE_ADMINISTRATOR = 1;
const TYPE_USER = 2;
const TYPE_GUEST = 3;
}
Suficientemente bueno:
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();
}
Ahora, la razón por la que elegí esos ejemplos es simple. La interfaz de User
está definiendo una enumeración de tipos de usuario. Es muy probable que se expanda con el tiempo y que se adapte mejor a otro patrón. Pero HTTPRequest_1_1
es un caso de uso decente, ya que la enumeración está definida por RFC2616 y no cambiará durante la vida de la clase.
En general, no veo el problema con las constantes y las constantes de clase como un problema global . Lo veo como un problema de dependencia. Es una distinción estrecha, pero definida. Veo problemas globales como variables globales que no se aplican, y como tal crean una dependencia global suave. Pero una clase codificada crea una dependencia forzada y, como tal, crea una dependencia global dura. Entonces ambas son dependencias. Pero considero que lo global es mucho peor ya que no se aplica ... Por eso no me gusta agrupar dependencias de clase con dependencias globales bajo el mismo letrero ...
Si escribe MyClass::FOO
, está codificado en los detalles de implementación de MyClass
. Esto crea un acoplamiento rígido, lo que hace que su código sea menos flexible y, como tal, debe evitarse. Sin embargo, existen interfaces para permitir exactamente este tipo de acoplamiento. Por MyInterface::FOO
tanto, MyInterface::FOO
no introduce ningún acoplamiento concreto. Dicho esto, no introduciría una interfaz solo para agregarle una constante.
Entonces, si está utilizando interfaces, y está seguro de que usted (o cualquier otra persona) no necesitará valores adicionales, entonces realmente no veo un gran problema con las constantes de la interfaz ... Lo mejor los diseños no incluirían ninguna constantes o condicionales o números mágicos o cadenas mágicas o nada codificado. Sin embargo, eso agrega tiempo adicional al desarrollo, ya que debe considerar los usos. Mi opinión es que la mayoría de las veces vale la pena tomarse el tiempo adicional para construir un gran diseño sólido. Pero hay momentos en que lo suficientemente bueno realmente es aceptable (y se necesita un desarrollador experimentado para entender la diferencia), y en esos casos está bien.
De nuevo, esa es solo mi opinión sobre eso ...
Las interfaces PHP permiten la definición de constantes en una interfaz, por ejemplo
interface FooBar
{
const FOO = 1;
const BAR = 2;
}
echo FooBar::FOO; // 1
Cualquier clase implementadora tendrá automáticamente estas constantes disponibles, por ejemplo
class MyFooBar implement FooBar
{
}
echo MyFooBar::FOO; // 1
Mi propia opinión sobre esto es que cualquier cosa Global es Evil . Pero me pregunto si lo mismo se aplica a Interface Constants. Dado que Codificar en una interfaz se considera una buena práctica en general, ¿está utilizando Constantes de interfaz las únicas constantes que son aceptables de usar fuera de un contexto de clase?
Si bien tengo curiosidad por escuchar su opinión personal y si usa las constantes de la interfaz o no, principalmente busco razones objetivas en sus respuestas. No quiero que esto sea una pregunta tipo Poll. Me interesa el efecto que tiene el uso de constantes de interfaz en la Mantenibilidad. Acoplamiento. O prueba de unidad. ¿Cómo se relaciona con SOLID PHP? ¿Viola algún principio de codificación que se considere una buena práctica en PHP? Entiendes la idea ...
Nota: hay una pregunta similar para Java que enumera algunas razones bastante buenas por las que son malas prácticas, pero como Java no es PHP, me pareció justificado volver a preguntar dentro de la etiqueta PHP.
Creo que generalmente es mejor manejar las constantes, especialmente las constantes enumeradas, como un tipo separado ("clase") de su interfaz:
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) { ... }
}
o, si desea usar una clase como espacio de nombres:
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) { ... }
}
No es que estés usando solo constantes, estás usando el concepto de valores enumerados o enumeraciones, que un conjunto de valores restringidos, se considera un tipo específico, con un uso específico ("dominio"?)