¿Por qué devolver un objeto en lugar de una matriz?

84

Trabajo mucho en WordPress y he notado que muchas más funciones devuelven objetos que matrices. Los resultados de la base de datos se devuelven como objetos a menos que solicite específicamente una matriz. Los errores se devuelven como objetos. Fuera de WordPress, la mayoría de las API le brindan un objeto en lugar de una matriz.

Mi pregunta es, ¿por qué usan objetos en lugar de matrices? En su mayor parte, no importa demasiado, pero en algunos casos encuentro los objetos más difíciles no solo de procesar, sino de entender. ¿Existe una razón de rendimiento para usar un objeto?

Soy un programador PHP autodidacta. Tengo un título en artes liberales. Así que perdóname si me falta un aspecto fundamental de la informática. ;)

Dennis
fuente
5
Tengo curiosidad por esto con respecto a las desventajas de los objetos, como no poder usar count()o array_*()funciones en ellos (al menos en lo que respecta a almacenar / devolver datos clave => valor). Nadie parece mencionarlo, ¿o me estoy perdiendo algo?
Wesley Murch
8
Los objetos se pueden hacer contables e iterables implementando interfaces contables o iteradoras. Consulte también php.net/manual/en/book.spl.php .
simshaun
Si tiene SPL instalado e implementa la interfaz contable para su clase de objeto, entonces puede llamar count()a un objeto.
Nadie se aleja del SE
2
En muchos casos, una matriz ni siquiera tiene sentido porque no devuelve una colección de objetos o un tipo de colección que no se emula fácilmente con matrices. Cuando solo tiene una secuencia de otros valores y no hay semántica adicional asociada, entonces, por el amor de Dios, devuelva una matriz, pero encontrará que rara vez es así.
8
@delnan y otros: tenga en cuenta que @Dennis está hablando de matrices asociativas (también conocidas como diccionarios, también conocidas como mapas), no matrices normales (de índice entero). Estas son una característica central de PHP y tienen más o menos el mismo propósito que las clases dinámicas ( stdClass). No estoy seguro de que esta pregunta tenga una respuesta que no sea "Porque los programadores que trabajan principalmente en OOP prefieren la semántica del uso de objetos"
BlueRaja - Danny Pflughoeft

Respuestas:

62

Estas son las razones por las que prefiero los objetos en general:

  • Los objetos no solo contienen datos sino también funcionalidad.
  • Los objetos tienen (en la mayoría de los casos) una estructura predefinida. Esto es muy útil para el diseño de API. Además, puede establecer propiedades como públicas, protegidas o privadas.
  • los objetos se ajustan mejor al desarrollo orientado a objetos.
  • En la mayoría de los IDE, el autocompletado solo funciona para objetos.

Aquí hay algo para leer:

Sascha Galley
fuente
3
el primer enlace parece no ser bueno? Quiero decir que funciona, pero lleva a un aritcle diferente
Geo
24

Probablemente esto no sea algo que vaya a comprender profundamente hasta que haya trabajado en un gran proyecto de software durante varios años. Muchos estudiantes recién graduados en ciencias de la computación le darán una respuesta con todas las palabras correctas (encapsulación, funcionalidad con datos y capacidad de mantenimiento), pero pocos entenderán realmente por qué es bueno tener todo eso.

Repasemos algunos ejemplos.

  • Si se devolvieron matrices, entonces todos los valores deben calcularse por adelantado o deben devolverse muchos valores pequeños con los que puede construir los valores más complejos.

Piense en un método de API que devuelva una lista de publicaciones de WordPress. Todas estas publicaciones tienen autores, los autores tienen nombres, direcciones de correo electrónico, tal vez incluso perfiles con sus biografías.

Si está devolviendo todas las publicaciones en una matriz, deberá limitarse a devolver una matriz de ID de publicación:

[233, 41, 204, 111]

o devolviendo una matriz masiva que se parece a:

[ title: 'somePost', body: 'blah blah', 'author': ['name': 'billy', 'email': '[email protected]', 'profile': ['interests': ['interest1', 'interest2', ...], 'bio': 'info...']] ]
[id: '2', .....]]

El primer caso de devolver una lista de ID no es muy útil para ti porque luego necesitas hacer una llamada a la API para cada ID para obtener información sobre esa publicación.

El segundo caso obtendrá mucha más información de la que necesita el 90% del tiempo y estará haciendo mucho más trabajo (especialmente si alguno de esos campos es muy complicado de construir).

Un objeto, por otro lado, puede proporcionarle acceso a toda la información que necesita, pero aún no ha obtenido esa información. La determinación de los valores de los campos se puede hacer de forma perezosa (es decir, cuando se necesita el valor y no de antemano) cuando se usa un objeto.

  • Las matrices exponen más datos y capacidades de las previstas

Vuelva al ejemplo de la matriz masiva que se devuelve. Ahora es probable que alguien construya una aplicación que repita cada valor dentro de la matriz de publicaciones y lo imprima. Si la API se actualiza para agregar solo un elemento adicional a esa matriz de publicaciones, entonces el código de la aplicación se romperá ya que imprimirá un campo nuevo que probablemente no debería. Si cambia el orden de los elementos en la matriz de publicaciones devuelta por la API, eso también romperá el código de la aplicación. Entonces, devolver una matriz crea todo tipo de posibles dependencias que un objeto no crearía.

  • Funcionalidad

Un objeto puede contener información dentro de él que le permitirá brindarle una funcionalidad útil. Un objeto de publicación, por ejemplo, podría ser lo suficientemente inteligente como para devolver las publicaciones anteriores o siguientes. Una matriz nunca podría hacer eso por ti.

  • Flexibilidad

Todos los beneficios de los objetos mencionados anteriormente ayudan a crear un sistema más flexible.

Matt Crinklaw-Vogt
fuente
10

Mi pregunta es, ¿por qué usan objetos en lugar de matrices?

Probablemente dos razones:

  • WordPress es bastante antiguo
  • las matrices son más rápidas y ocupan menos memoria en la mayoría de los casos
  • más fácil de serializar

¿Existe una razón de rendimiento para usar un objeto?

No. Pero muchas otras buenas razones, por ejemplo:

  • puede almacenar lógica en los objetos (métodos, cierres, etc.)
  • puede forzar la estructura del objeto usando una interfaz
  • mejor autocompletado en IDE
  • no recibe avisos para claves de matriz no definidas
  • al final, puede convertir fácilmente cualquier objeto en una matriz

¡ OOP ! = AOP :)

(Por ejemplo, en Ruby, todo es un objeto. Anteriormente PHP era un lenguaje de procedimientos / secuencias de comandos).

tomando
fuente
7

WordPress (y una buena cantidad de otras aplicaciones PHP) usa objetos en lugar de matrices, por razones conceptuales más que técnicas.

Un objeto (incluso si solo es una instancia de stdClass) es una representación de una cosa. En WordPress, puede ser una publicación, un comentario o un usuario. Una matriz, por otro lado, es una colección de cosas. (Por ejemplo, una lista de publicaciones).

Históricamente, PHP no ha tenido un gran soporte de objetos, por lo que las matrices se volvieron bastante poderosas desde el principio. (Por ejemplo, la capacidad de tener claves arbitrarias en lugar de tener un índice cero). Con el soporte de objetos disponible en PHP 5, los desarrolladores ahora pueden elegir entre usar matrices u objetos como almacenes de clave-valor. Personalmente, prefiero el enfoque de WordPress porque me gusta la diferencia sintáctica entre 'entidades' y 'colecciones' que proporcionan los objetos y las matrices.

Seb Pollard
fuente
5

Mi pregunta es, ¿por qué (Wordpress) usan objetos en lugar de matrices?

Esa es realmente una buena pregunta y no es fácil de responder. Solo puedo asumir que es común en Wordpress usar stdClassobjetos porque están usando una clase de base de datos que, por defecto, devuelve registros como un stdClassobjeto. Se acostumbraron (8 años y más) y ya está. No creo que haya mucho más pensamiento detrás del simple hecho.

azúcar sintáctica para matrices asociativas - Zeev Suraski sobre el objeto estándar desde PHP 3

  • stdClasslos objetos no son realmente mejores que las matrices. Son más o menos lo mismo. Eso es por algunas razones históricas del lenguaje y los stdClassobjetos son realmente limitados y en realidad son solo una especie de objetos de valor en un sentido muy básico.
  • stdClasslos objetos almacenan valores para sus miembros como lo hace una matriz por entrada. Y eso es.
  • Solo los fanáticos de PHP pueden crear stdClassobjetos con miembros privados. No hay mucho beneficio, si es que lo hay, al hacerlo.
  • stdClasslos objetos no tienen ningún método / función. Así que no hay uso de eso en Wordpress.
  • En comparación con array, hay funciones mucho menos útiles para tratar con una lista o datos semiestructurados.

Sin embargo, si está acostumbrado a las matrices, simplemente transmita:

$array = (array) $object;

Y puede acceder a los datos previamente siendo un objeto, como una matriz. O te gusta al revés:

$object = (object) $array;

Lo que solo eliminará nombres de miembros no válidos, como números. Así que ten un poco de cuidado. Pero creo que entiendes el panorama general: no hay mucha diferencia siempre que se trate de matrices y objetos de stdClass.

Relacionado:

hakre
fuente
4
  1. El código se ve más genial de esa manera
  2. Los objetos pasan por referencia
  3. Los objetos tienen un tipo más fuerte que las matrices, por lo tanto, lees pron a errores (o le dan un mensaje de error significativo cuando intenta usar un miembro no existente)
  4. Todos los IDE de hoy tienen autocompletar, por lo que cuando se trabaja con objetos definidos, el IDE hace mucho por usted y acelera las cosas.
  5. Encapsule fácilmente la lógica y los datos en la misma caja, donde con las matrices, almacena los datos en la matriz y luego usa un conjunto de funciones diferentes para procesarlos.
  6. Herencia, si tuviera una matriz similar con una funcionalidad casi pero no similar, tendría que duplicar más código que si va a hacerlo con objetos

Probablemente alguna razón más por la que he pensado

Itay Moav -Malimovka
fuente
"# Los objetos pasan por referencia": Eso es incorrecto. Los objetos no pasan como una referencia de variable PHP. Nunca lo hicieron.
hakre
@hakre - ¿estás en php4? o por favor explique lo que quiere decir.
Itay Moav -Malimovka
Bueno, no es que wordpress no fuera PHP 4 hasta hace poco, pero en PHP 4 o PHP 5, los objetos no pasan como referencia: "Uno de los puntos clave de PHP5 OOP que se menciona a menudo es que" los objetos se pasan por referencias por defecto " . Esto no es completamente cierto. Esta sección rectifica ese pensamiento general usando algunos ejemplos ". Objetos y referencias
hakre
@hakre: veo lo que quieres decir, pero a todos los efectos, el lenguaje se comporta como si solo pasaras referencias.
Itay Moav -Malimovka
4

Los objetos son mucho más poderosos que las matrices. Cada objeto como instancia de una clase puede tener funciones adjuntas. Si tiene datos que necesitan procesamiento, entonces necesita una función que realice el procesamiento. Con una matriz, tendría que llamar a esa función en esa matriz y, por lo tanto, asociar la lógica usted mismo a los datos. Con un objeto, esta asociación ya está hecha y ya no tiene que preocuparse por ella.

También debe considerar el principio OO de ocultar información. No se debe poder acceder directamente a todo lo que regresa o va a la base de datos.

Nadie se aleja del SE
fuente
Wordpress devuelve objetos de la clase StdClass. Esos objetos no tienen nada en común con lo que resaltas. No tienen funciones, por ejemplo, y no tienen herencia. Y en el caso de Wordpress, todas las variables de clase son públicas.
hakre
Si eso es verdad. Creo que en este caso, como han dicho otros, depende de lo que prefieras. No me gusta wordpress, pero probablemente encapsulan todas las llamadas a la base de datos y, por lo tanto, no pueden proporcionar ninguna clase especializada para regresar. Pero mi respuesta fue en general y creo que los creadores hicieron consideraciones similares ... O simplemente lanzaron una moneda.
Nadie se va de SE
Simplemente usan una clase auxiliar de base de datos que devuelve stdClassobjetos de forma predeterminada desde ca. 8 años. Si desea obtener una matriz, debe establecer un parámetro opcional para obtenerla.
hakre
3

Hay varias razones para devolver objetos:

  1. La escritura $myObject->propertyrequiere menos caracteres "generales" que$myArray['element']

  2. El objeto puede devolver datos y funcionalidad; las matrices solo pueden contener datos.

  3. Habilitar encadenamiento: $myobject->getData()->parseData()->toXML();

  4. Codificación más sencilla: el autocompletado IDE puede proporcionar sugerencias sobre métodos y propiedades para el objeto.

En términos de rendimiento, las matrices suelen ser más rápidas que los objetos. Además del rendimiento, existen varias razones para utilizar matrices:

  1. La funcionalidad proporcionada por la familia de funciones array _ * () puede reducir la cantidad de codificación necesaria en algunos casos.

  2. Las operaciones como count () y foreach () se pueden realizar en matrices. Los objetos no ofrecen esto (a menos que implementen Iterator o Countable ).

George Cummins
fuente
2

Por lo general, no será por motivos de rendimiento. Normalmente, los objetos cuestan más que las matrices.

Para muchas API, probablemente tenga que ver con los objetos que brindan otra funcionalidad además de ser un mecanismo de almacenamiento. De lo contrario, es una cuestión de preferencia y realmente no hay ningún beneficio en devolver un objeto frente a una matriz.

Simshaun
fuente
En PHP5, la diferencia de rendimiento entre matrices y objetos es marginal.
Justin ᚅᚔᚈᚄᚒᚔ
2

Una matriz es solo un índice de valores. Mientras que un objeto contiene métodos que pueden generar el resultado para usted. Claro, a veces puede acceder a los valores de un objeto directamente, pero la "forma correcta de hacerlo" es acceder a los métodos de un objeto (una función que opera sobre los valores de ese objeto).

$obj = new MyObject;
$obj->getName();   // this calls a method (function), so it can decide what to return based on conditions or other criteria

$array['name'];   // this is just the string "name". there is no logic to it. 

A veces accedes a las variables de un objeto directamente, esto generalmente está mal visto, pero sucede con bastante frecuencia.

$obj->name;   // accessing the string "name" ... not really different from an array in this case.

Sin embargo, considere que la clase MyObject no tiene una variable llamada 'nombre', sino que tiene una variable nombre y apellido.

$obj->getName();  // this would return first_name and last_name joined.
$obj->name;  // would fail...
$obj->first_name; 
$obj->last_name; // would be accessing the variables of that object directly.

Este es un ejemplo muy simple, pero puede ver a dónde va. Una clase proporciona una colección de variables y las funciones que pueden operar sobre esas variables, todo dentro de una entidad lógica autónoma. Una instancia de esa entidad se llama objeto e introduce resultados lógicos y dinámicos, que una matriz simplemente no tiene.

Nick Jennings
fuente
1

La mayoría de las veces, los objetos son tan rápidos, si no más rápidos que las matrices, en PHP no hay una diferencia notable. la razón principal es que los objetos son más poderosos que las matrices. La programación orientada a objetos le permite crear objetos y almacenar no solo datos, sino funcionalidad en ellos, por ejemplo, en PHP, la clase MySQLi le permite tener un objeto de base de datos que puede manipular utilizando una serie de funciones incorporadas, en lugar del enfoque procedimental.

Entonces, la razón principal es que la programación orientada a objetos es un paradigma excelente. Escribí un artículo sobre por qué usar POO es una buena idea y, para explicar el concepto, puedes echarle un vistazo aquí: http://tomsbigbox.com/an-introduction-to-oop/

Como ventaja menor, también escribe menos para obtener datos de un objeto - $ test-> data es mejor que $ test ['data'].

Tom Walters
fuente
1

No estoy familiarizado con la prensa escrita. Muchas respuestas aquí sugieren que una de las ventajas de los objetos es su capacidad para contener código funcional. Cuando se devuelve un objeto de una función / llamada a la API, no debe contener funciones de utilidad. Solo propiedades.

La fortaleza de devolver objetos es que cualquier cosa que se encuentre detrás de la API puede cambiar sin romper su código.

Ejemplo: obtiene una matriz de datos con pares clave / valor, la clave representa la columna DB. Si se cambia el nombre de la columna DB, su código se romperá.

Josh Johnson
fuente
1

Estoy ejecutando la siguiente prueba en php 5.3.10 (windows):

for ($i = 0; $i < 1000000; $i++) {
    $x = array();
    $x['a'] = 'a';
    $x['b'] = 'b';
}

y

for ($i = 0; $i < 1000000; $i++) {
    $x = new stdClass;
    $x->a = 'a';
    $x->b = 'b';
}

Copiado de http://atomized.org/2009/02/really-damn-slow-a-look-at-php-objects/comment-page-1/#comment-186961

Llamar a la función para 10 usuarios concurrentes y 10 veces (para obtener un promedio) luego

  • Matrices: 100%
  • Objeto: 214% - 216% (2 veces más lento).

AKA, Object es todavía doloroso lento. OOP mantiene las cosas ordenadas, sin embargo, debe usarse con cuidado.

¿Qué aplica Wordpress ?. Bueno, ambas soluciones están usando objetos, matrices y objetos y matrices, la clase wpdb usa la última (y es el corazón de Wordpress).

magallanes
fuente
Debería ver la comparación en PHP 5.4. El rendimiento de los objetos es sobresaliente y, a veces, incluso más rápido que las matrices.
Sanket Sahu
0

Sigue el principio de boxeo y unboxing de OOP. Mientras que lenguajes como Java y C # admiten esto de forma nativa, PHP no. Sin embargo, se puede lograr, hasta cierto punto en PHP, pero no de manera elocuente ya que el lenguaje en sí no tiene construcciones que lo respalden. Tener tipos de caja en PHP podría ayudar con el encadenamiento, manteniendo todo orientado a objetos y permite la sugerencia de tipo en las firmas de métodos. La desventaja es la sobrecarga y el hecho de que ahora tiene que realizar comprobaciones adicionales utilizando la construcción "instancia de". Tener un sistema de tipos también es una ventaja cuando se utilizan herramientas de desarrollo que tienen intellisense o asistencia de código como PDT. En lugar de tener que buscar en google / bing / yahoo para el método, existe en el objeto y puede usar la herramienta para proporcionar un menú desplegable.

LEMUEL ADANE
fuente
0

Aunque los puntos señalados acerca de que los objetos son más que simples datos son válidos, ya que generalmente son datos y comportamiento, hay al menos un patrón mencionado en "Patrones de arquitectura de aplicaciones empresariales" de Martin Fowler. que se aplica a este tipo de cenario en el que está transfiriendo datos de un sistema (la aplicación detrás de la API) y otro (su aplicación).

Es el objeto de transferencia de datos : un objeto que transporta datos entre procesos para reducir el número de llamadas a métodos.

Entonces, si la pregunta es si las API deben devolver un DTO o una matriz, diría que si el costo de rendimiento es insignificante, entonces debe elegir la opción que sea más fácil de mantener, que yo diría que es la opción DTO ... pero, por supuesto, también Debe considerar las habilidades y la cultura del equipo que está desarrollando su sistema y el idioma o soporte IDE para cada una de las opciones.

Vitor Silva
fuente