2011-03-02 11 views
14

Tuve una discusión con un colega sobre si esta es una mala práctica o no. Ahora no puedo encontrar ejemplos inmediatos de esto en línea.Método estático get - is this bad bad practice?

Tenemos una gran cantidad de objetos mappers base de datos y llamamos Sus funciones como tal

(ejemplo) - el método setId conseguir es la fila de la base de datos y establece es que propertys predefinidos

class Person { 

    public static function get($id) { 
     $object = new Person; 
     $object->setId($id); 
     return $object; 
    } 
} 

Usándolo como esto podemos utilizar construcciones simples de esta manera: (donde nos dieron el id de para-ejemplo un post)

$person = Person::get($id); 

en lugar de

$person = new Person; 
$person->setId($id); 

Ahora, mi instinto me dice que esto es una mala práctica. Pero no puedo explicarlo. Tal vez alguien aquí puede explicar por qué esto es, o no es una mala práctica

Aquí hay algunos otros ejemplos de cómo lo usamos. lo usamos principalmente para getters. (Sólo los nombres, no el código. Casi todos ellos sólo ejecutar una consulta, que puede volver 1 objeto y luego utilizar el identificador del resultado de utilizar el método setId)

class CatalogArticle { 
    public static function get($id) { } 
    public static function getByArticlenumber($articlenumber) {} //$articlenumber is unique in the database 
    public static function getRandom() {} //Runs a query returning a random row 
} 
+0

* (relacionados) * http://stackoverflow.com/questions/5166087/php-global-in-functions/5166527#5166527 – Gordon

+0

Sólo mis dos centavos, pero Taylor Otwell de laravel consiguió calor debido a su uso de métodos estáticos de patrones de fábrica y otros métodos estáticos, pero adivine qué cobertura del 100% de la unidad. –

Respuesta

12

Esto no es horrible persay. Es una implementación de un patrón de diseño Factory Method. No está nada mal en principio.

Sin embargo, en su ejemplo específico, en realidad no está haciendo nada significativo, por lo que no estoy seguro de si es necesario. Puede eliminar la necesidad tomando un parámetro (tal vez opcional) para el constructor de la identificación. Entonces, cualquiera puede llamar al $foo = new Person($id); en lugar de necesitar una fábrica explícita.

Pero si la creación de instancias es compleja, o si desea la capacidad de crear diferentes tipos de personas que solo pueden determinarse por lógica, un método de fábrica puede funcionar mejor. Por ejemplo, supongamos que necesita determinar el tipo de persona para instanciar por algún parámetro. Entonces, un método de fábrica en Person sería apropiado. El método determinará qué "tipo" cargar y, a continuación, instanciará esa clase.

Las estáticas en general son difíciles de probar y no permiten cambios polimórficos como lo haría una instancia. También crean dependencias duras entre clases en el código. No son horrible, pero realmente deberías pensar si quieres usar uno. Una opción sería usar un Builder o un Abstract Factory. De esta forma, crea una instancia del constructor/fábrica y luego deja que esa instancia determine cómo crear una instancia de la clase resultante ...

Otra nota. Cambiaría el nombre de ese método de Person::get() a algo un poco más semánticamente apropiado. Tal vez Person::getInstance() o algo más apropiado.

5

Este blog debe decirle por qué las personas no les gusta los métodos estáticos mejor que pude:

http://kore-nordmann.de/blog/0103_static_considered_harmful.html

La pregunta que más me sorprende sobre el fragmento de código actual: es una persona permite que no tiene un ID?

Creo que debería ser un argumento constructor si representa a una persona real. Si usas esa clase para crear nuevas personas, es posible que no funcione.


La diferencia entre las 2 llamadas es menor. Ambos "crean" una clase Person y configuran el Id para que no ganes/pierdas nada allí cuando se trata de "dependencias cableadas".

La ventaja solo se muestra cuando desea poder pasar una Persona a otro objeto y esos objetos deben cambiar la ID (como ejemplo, la publicación del blog debe explicarlo mejor que aquí).

2

Solo estoy agregando a la publicación de edorian, pero he usado métodos de obtención estáticos en el pasado, donde hay un motor de almacenamiento en caché, y (por ejemplo) podría tener un objeto Person dado en Memcache, y preferiría recuperarlo del caché que ir a la base de datos.

Por ejemplo:

class Person { 

    public static function get($id) { 

     if(Cache::contains("Person", $id)) 
     { 
      return Cache::get("Person", $id); 
     } 
     else 
     {   
      //fictional get_person_from_database, basically 
      //getting an instance of Person from a database 
      $object = get_person_from_database($id); 
     } 
     return $object; 
    } 

} 

De esta manera, todo el manejo de la memoria caché es realizado por la clase en cuestión, en lugar de la persona que llama conseguir una persona llama tener que preocuparse acerca de la caché.

1

cuento largo, sí, son malas prácticas:

Una buena razón, aparte de todo es que 'debe' ser probar su código. Los métodos estáticos causar problemas, por lo que hay que tener una buena razón:

  • si desea seguir las buenas prácticas, probar el código
  • Ergo, si causas estáticas problemas de pruebas, estática evitar escribir las pruebas por lo que impide seguir buenas prácticas :-)
Cuestiones relacionadas