php - Métodos independientes de getter/setter, o combinados?
oop naming-conventions (7)
¿Por qué no hacerlo así?
public function someProperty($value = null)
{
if (func_num_args() === 1) {
$this->someProperty = $value;
return $this;
} else {
return $this->someProperty;
}
}
Esta sería la única forma correcta de implementar un captador / configurador combinado
Mientras trabajaba en un proyecto, he estado realizando algunos cambios y explorando los documentos existentes de la API del marco para obtener información.
Al leer detenidamente los documentos de Kohana, noté que los captadores / definidores de cualquier clase dada se combinan típicamente:
public function someProperty($value = null){
if(is_null($value){
return $this->_someProperty;
}
$this->_someProperty = $value;
return $this;
}
Más bien que:
public function setSomeProperty($value){
$this->_someProperty = $value;
return $this;
}
public function getSomeProperty(){
return $this->_someProperty;
}
¿Hay algún valor en hacer esto ( el primero ), más allá de disminuir el conteo de métodos de una clase dada? Siempre entendí que los métodos ( funciones en general ) deberían ser más descriptivos de una acción. ¿Otros desarrolladores experimentados se estremecen, incluso un poquito, cuando ven esto?
Me sorprendió ver un marco popular que usa tales convenciones ( no he usado Kohana, por supuesto )
A pesar del hecho de que Kohana usa una técnica tan inusual para la POO, creo que al principio debes seguir las convenciones de codificación. Pero, por supuesto, es mejor usar getters y setters separados para cada propiedad en sus clases. Entonces, si es posible usarlos sin romper las convenciones, simplemente hazlo y no estarás equivocado;). También puede leer aquí sobre buenos hábitos en PHP OOP - http://www.ibm.com/developerworks/opensource/library/os-php-7oohabits/ si ha dudado acerca del uso de algunas técnicas de OOP. Espero que te ayude :)
Considero esta mala práctica porque viola CommandQuerySeparation . Establecer un valor es cambiar el estado (Comando). Obtener un valor es pedir estado (consulta). Un método no debe hacer ambas cosas, sino una sola cosa.
Además, no es realmente obvio lo que hace un método cuando se llama simplemente nombre de usuario, por ejemplo, no tiene un verbo, como obtener o establecer. Esto empeora aún más en su ejemplo, porque el valor de retorno es el objeto en sí o el valor de la propiedad, por lo que no es consistente.
Además, los captadores (y los definidores) deben usarse con moderación, ya que rápidamente convolucionarán su API. Cuantos más getters y setters tengas, más conocimiento de un objeto es requerido por los colaboradores de ese objeto. Si encuentra que sus objetos le preguntan a otros objetos sobre sus aspectos internos, es probable que haya perdido las responsabilidades.
Por el valor del argumento,
El enfoque combinado ofrece algunos beneficios:
- Evita
__get
y__set
magic mientras emula una propiedad pública. (De todos modos, nunca recomendaría usar magia para estas situaciones) - Usar
thing()
es menos detallado que usargetThing() setThing()
. - Aunque los métodos harán más, aún pueden considerarse como "hacer una
thing()
", es decir, manejar lathing()
. Las propiedades también hacen más de una cosa. Te permiten establecer y obtener valores. - Se argumenta que la
thing()
no da un verbo. Sin embargo, podemos suponer que unathing()
sin un verbo significa que lo usamos como una propiedad (lo obtenemos y lo configuramos ). Para las interfaces, podemos decir que unathing()
sin argumento es de solo lectura y unathing($arg)
con un argumento es de lectura / escritura . ¿Por qué deberíamos ser tímidos de adoptar esto? En algún momento adoptamos la idea de agregar captadores y definidores, ¿no? - Si está utilizando un lenguaje basado en la web (como PHP), es probable que también esté usando jQuery. JQuery ya está haciendo este tipo de
thing()
y ha funcionado bien. - El uso de
func_num_args()
, como ya se mencionó, ayuda a lograr este enfoque perfectamente.
Personalmente, en este momento ya he asumido una buena parte de los riesgos en mis aplicaciones actuales, así que probablemente voy con los viejos buscadores y definidores probados ( consulte la sección "Encontrar el equilibrio" de la publicación de Jimmy Bogard en En lo que respecta a los getters / setters para operaciones de datos ). Y supongo que ya estamos capacitados para buscar estos prefijos de obtención / configuración (así como nuestro IDE) para ver con qué propiedades podemos trabajar en una clase. Esta es una discusión a la que me gustaría volver en algún momento.
Prefiero creer que tenían una explicación razonable para hacerlo de esta manera. Por ejemplo, para una implementación más fácil de ArrayAccess. La única forma de saberlo con seguridad es preguntándoles directamente.
Para responder a tu pregunta, sí, me estremezco cuando veo el primer método. Va en contra de los principios de la POO.
Si lo haces en cualquier lugar, es una buena manera, pero de lo que realmente tiene que ser para todo , tal vez los programadores de este framework estén acostumbrados, (es un poco jquery por igual)
Sin embargo me confundiría
Para configurar y obtener siempre utilizo setters y getters :
public function __set($key, $value) {
// assign value $value to $this->key
}
public function __get($key) {
// return value of this->key
}
jQuery va de la misma manera que Kohana. Sin embargo, creo que es mejor crear métodos separados para establecer y obtener. Es más obvio lo que hace el método y creo que es más práctico para completar el código en su ide. Por ejemplo, escribe set
y obtiene una lista de todas las propiedades que puede establecer.
Otra desventaja es: ¿qué sucede si realmente desea establecer un valor en null
? Esto no funcionaría ya que el null
es el identificador para el retorno en el valor, está restringido en la configuración de valores específicos ...
Así que es bueno, ya que tendrás que escribir menos, pero ¿qué son tres letras ( set
/ get
) frente a tus métodos?