2010-07-07 23 views
60

En medio de un período de grandes refactorizaciones en el trabajo, deseo presentar stdClass ***** como una forma de devolver datos de las funciones y estoy tratando de encontrar argumentos no subjetivos para respaldar mi decisión.¿Cuándo debería usar stdClass y cuándo debería usar una matriz en php oo?

¿Hay alguna situación en la que sería mejor usar una en lugar de la otra?

¿Qué beneficios obtendré al utilizar stdClass en lugar de matrices?


Algunos dirán que las funciones tienen que ser tan pequeña y específica para poder volver un solo valor. Mi decisión de usar stdClass es temporal, ya que espero encontrar los objetos de valor correctos para cada proceso en el largo plazo.

+0

ver: http://stackoverflow.com/questions/2056931/value-objects-vs-associative-arrays-in-php No responde mi pregunta. Él dice que una clase "real" sería el mejor enfoque, que (creo) todos estamos de acuerdo. Me gustaría saber "cuándo" el uso de stdClass devuelve valores es mejor que las matrices. – JonG

+0

es posible que desee aclarar su concepto de objetos de valor. [En DDD, un objeto de valor es inmutable] (http://domaindrivendesign.org/node/135) y el propósito es bastante diferente de [VOs en Java.] (Http://java.sun.com/j2ee/patterns/ ValueObject.html) – Gordon

+0

@Gordon Lo que quise decir fue una guía de retorno "VO-like" de las funciones. Tener un VO como un objeto (preferiblemente) pequeño, donde solo sus atribuciones son importantes, no su identidad. Acerca de sus enlaces, ¿estaba tratando de averiguar si para mí (mi pregunta) era importante la discusión sobre "VO debe ser inmutable Vs VO puede ser mutable"? Por cierto, hoy en día los VO son A (objetos de transferencia) para el sol. http://java.sun.com/blueprints/corej2eepatterns/Patterns/TransferObject.html – JonG

Respuesta

52

El enfoque habitual es

  • Usar objetos al devolver una estructura de datos definida con ramas fijas:

    $person 
        -> name = "John" 
        -> surname = "Miller" 
        -> address = "123 Fake St" 
    
  • Use arrays al devolver una lista:

    "John Miller" 
        "Peter Miller" 
        "Josh Swanson" 
        "Harry Miller" 
    
  • Usa una matriz de objetos cuando regreses ing una lista de información estructurada:

    $person[0] 
        -> name = "John" 
        -> surname = "Miller" 
        -> address = "123 Fake St" 
    
        $person[1] 
        -> name = "Peter" 
        -> surname = "Miller" 
        -> address = "345 High St" 
    

Los objetos no son adecuados para mantener listas de datos, porque siempre se necesita una llave para hacerles frente. Las matrices pueden cumplir ambas funciones: mantener listas arbitrarias y una estructura de datos.

Por lo tanto, puede usar matrices asociativas sobre objetos para el primer y tercer ejemplo si lo desea. Diría que es solo una cuestión de estilo y preferencia.

@Deceze hace una serie de buenos comentarios sobre cuándo usar un objeto (Validación, verificación de tipo y métodos futuros).

+0

+1 buena respuesta detallada. – Sarfraz

+0

Me gustan/estoy de acuerdo con los argumentos número 1 y 2. – JonG

+1

Pedí argumentos "no-subjetivos". Lamentablemente, ninguno fue dado. Me atengo a su respuesta (siguiendo los votos de otros), ya que muestra lo que seguiré a partir de ahora: las matrices son para listas; stdClass para "multi-valor"/propiedades. – JonG

37

El uso de stdClass para cumplir la misma función que una matriz no es muy útil en mi humilde opinión, simplemente agrega la sobrecarga de un objeto sin ningún beneficio real. También se está perdiendo muchas funciones de matriz útiles (por ejemplo, array_intersect). Al menos debe crear su propia clase para habilitar la comprobación de tipos o agregar métodos al objeto para que valga la pena usar un objeto.

+1

Me gusta/acepto especialmente lo que dices sobre "agregar métodos al objeto para que valga la pena usarlo". – JonG

3

Bueno, hay diferencias: 3

  • que tienen una identidad. por lo que el valor predeterminado para pasar argumentos de matriz es llamar por valor y para los objetos llamar al compartir.
  • hay una diferencia semántica. Si utiliza un objeto, cualquiera que lea el código lo comprenda, que el valor represente al modelo algún tipo de entidad, mientras que una matriz se supone que debe actuar como una colección o un mapa
  • Y por último pero no menos importante, la refactorización se vuelve significativamente más fácil . Si desea utilizar una clase concreta en lugar de stdClass, todo lo que tiene que hacer es crear una instancia de otra clase. Lo cual también le permite agregar métodos.

greetz
back2dos

16

No creo que haya ninguna ventaja razonable de utilizar un stdClass sobre un arsenal siempre que su única intención es devolver varios tipos de datos arbitrarios de una llamada a la función.

Dado que técnicamente no puede devolver múltiples valores de forma nativa, debe usar un contenedor que pueda contener todos los demás tipos de datos disponibles en PHP. Eso sería un objeto o una matriz.

function fn1() { return array(1,2); } 
function fn2() { return array('one' => 1, 'two' => 2); } 
function fn3() { return (object) array(1,2); } 
function fn4() { return (object) array('one' => 1, 'two' => 2); } 

Todo lo anterior funcionaría. La matriz es una pequeña fracción insignificante más rápida y menos trabajo de tipeo. También tiene un propósito claramente definido en contraste con el stdClass genérico (que es un poco desagradable, ¿verdad?). Ambos solo tienen una interfaz implícita, por lo que tendrás que mirar los documentos o el cuerpo de la función para saber qué contendrán.

Si desea utilizar objetos a cualquier costo, puede usar ArrayObject o SplFixedArray, pero si mira sus API, ¿diría que necesita su funcionalidad para la simple tarea de devolver valores múltiples aleatorios? No lo creo. Sin embargo, no me malinterprete: si quiere usar stdClass, entonces úselo. No es como si rompiera cualquier cosa. Pero tampoco ganarías nada. Para agregar al menos algún beneficio, puede crear una clase separada denominada ReturnValues ​​para esto.

podría ser una clase simple etiquetado

class ReturnValues {} 

o algo más funcional

class ReturnValues implements Countable 
{ 
    protected $values; 
    public function __construct() { $this->values = func_get_args(); } 
    public function __get($key) return $this->values[$key]; } 
    public function count() { return count($this->values); } 
} 

Por supuesto, no hace mucho y conseguir los valores fuera de él todavía se realiza a través de una interfaz implict , pero al menos la clase tiene ahora una responsabilidad más claramente definida. Se podría extender de esta clase para crear objetos ReturnValue para determinadas operaciones y dar a aquellos de una interfaz explícita:

class FooReturnValues extends ReturnValues 
{ 
    public function getFoo() { return $this->values['foo']; } 
    public function getBar() { return $this->values['foo']; } 
} 

Ahora el desarrollador sólo tiene que mirar a la API para saber qué valores múltiples foo() devolverá. Por supuesto, tener que escribir clases concretas de ReturnValue para cada operación que pueda devolver múltiples valores puede volverse tedioso rápidamente. Y personalmente, creo que esto se inventó para el propósito inicial.

De todos modos, espero que tenga sentido.

+1

interesante su propuesta "ReturnValues". – JonG

+0

@JonG Gracias. Supongo que mis dos puntos principales son: hacer que el objeto devuelto sea semánticamente más claro y hacer que la interfaz sea explícita. Si nada de eso importa, entonces no sirve de nada seguir esa ruta imo. – Gordon

+0

Me gusta esta idea de una clase que es genérica, pero genérica dentro de un dominio/propósito particular. Tiene el potencial de realmente agregar potencia, mientras que 'stdClass' es poco más que una representación alternativa de una matriz asociativa. – IMSoP

2

Encuentro los objetos stdClass sobre las matrices útiles cuando necesito mantener mi código limpio y algo legible. Tomemos por ejemplo la función getProperties() que devuelve un conjunto de propiedades, por ejemplo datos sobre una persona (nombre, edad, sexo).Si getProperties() volvería una matriz asociativa, cuando se desea utilizar una de las propiedades devueltas, podría escribir dos instrucciones:

$data = getProperties(); 
echo $data['name']; 

Por otro lado, si getProperties() devuelve un stdClass entonces se podría escribir que en un solo instrucciones:

echo getProperties()->name; 
+3

Tenga en cuenta que esto ya no se aplica si está utilizando PHP 5.4 o posterior, ya que fue solo una pequeña parte del analizador de PHP. Ahora puede escribir 'echo getProperties() ['name'];' http://3v4l.org/t6i0r – IMSoP

+0

@IMSoP, puede, excepto que muchos sistemas aún usan PHP 5.3, lo que arrojará un error que desconcertará algunos desarrolladores :). – musicliftsme

+1

@laketuna Sí, de ahí el "si" en mi comentario :) Tenga en cuenta también que 5.3 ahora no está oficialmente admitido, por lo que las personas deberían molestar a sus hosts/administradores para actualizar: http://php.net/eol.php – IMSoP

2

El único voto Objetivo de la confianza que puedo encontrar es:

json_decode utiliza stdClass de forma predeterminada para nosotros los mortales en espacio de usuario deben utilizar stdClass para situaciones similares.

+3

puede solo use 'json_decode ($ json, true);' si quiere obtener arrays en lugar de objetos – Peter

+0

nosotros los mortales en userland no 'solo' anulamos los valores predeterminados de param. – tishma

1

En las pruebas de array vs stclass, php maneja las propiedades dinámicas de manera que las matrices asociativas sean más lentas. No digo esto para argumentar la micro optimización, sino que si va a hacer esto, será mejor que defina una clase de datos sin métodos y establezca propiedades públicas. Esp si estás usando php 5.4+. Debajo de las características definidas de la capucha, se asignan directamente a una matriz c sin hashtable donde las dinámicas necesitan usar una tabla hash.

Esto tiene la ventaja añadida de convertirse más adelante en una clase completa sin necesidad de volver a trabajar en la interfaz.

+0

Las características de rendimiento de PHP cambian con cada versión. –

Cuestiones relacionadas