Pregunta

(Esta pregunta se utiliza PHP como contexto, pero no se limita a PHP solamente. Cualquier lenguaje, por ejemplo, con una función de hash en también es relevante)

Veamos este ejemplo (PHP):

function makeAFredUsingAssoc()
{
    return array(
        'id'=>1337,
        'height'=>137,
        'name'=>"Green Fred");
}

Versus:

class Fred
{
    public $id;
    public $height;
    public $name;

    public function __construct($id, $height, $name)
    {
        $this->id = $id;
        $this->height = $height;
        $this->name = $name;
    }
}

function makeAFredUsingValueObject()
{
    return new Fred(1337, 137, "Green Fred");
}

Método # 1 es de más concisa supuesto, sin embargo, puede conducir fácilmente a error como

$myFred = makeAFredUsingAssoc();
return $myFred['naem']; // notice teh typo here

Por supuesto, se podría argumentar que $myFred->naem será igualmente conducir a error, lo cual es cierto. Sin embargo, tener una clase formal sólo se siente más rígido para mí, pero no puedo justificarlo.

¿Cuáles serían las ventajas / desventajas de utilizar cada enfoque y cuando la gente debe utilizar qué enfoque?

¿Fue útil?

Solución

Bajo la superficie, los dos enfoques son equivalentes. Sin embargo, se obtiene la mayor parte de los beneficios OO estándar cuando se utiliza una clase:. Encapsulación, herencia, etc.

También, busque en los siguientes ejemplos:

$arr['naem'] = 'John';

es perfectamente válido y podría ser un error difícil de encontrar.

Por otro lado,

$class->setNaem('John');

nunca funcionará.

Otros consejos

Una clase simple como la siguiente:

class PersonalData {
    protected $firstname;
    protected $lastname;

    // Getters/setters here
}

tiene pocas ventajas sobre una matriz.

  1. No hay posibilidad de hacer algunos errores tipográficos. $data['firtsname'] = 'Chris'; funcionará mientras $data->setFirtsname('Chris'); lanzará en error.
  2. Tipo dando a entender:. Arrays PHP pueden contener todo (incluyendo nada) mientras que la clase bien definida sólo contiene datos especificados

    public function doSth(array $personalData) {
        $this->doSthElse($personalData['firstname']); // What if "firstname" index doesn't exist?
    }
    
    
    public function doSth(PersonalData $personalData) {
        // I am guaranteed that following method exists. 
        // In worst case it will return NULL or some default value
        $this->doSthElse($personalData->getFirstname());
    }
    
  3. puede añadir algo de código adicional antes establecido / operaciones, como la validación o registro:

    public function setFirstname($firstname) {
        if (/* doesn't match "firstname" regular expression */) {
            throw new InvalidArgumentException('blah blah blah');
        }
    
    
    
    if (/* in debbug mode */) {
        log('Firstname set to: ' . $firstname);
    }
    
    
    $this->firstname = $firstname;
    
    }
  4. Se puede utilizar todas las ventajas de la programación orientada a objetos como la herencia, polimorfismo, dando a entender tipo, encapsulación y así sucesivamente ...
  5. Como se ha mencionado antes de que todos nuestros "estructuras" puede heredar de una clase base que proporciona la implementación para las interfaces Countable, Serializable o Iterator, por lo que nuestras estructuras podrían utilizar foreach bucles, etc.
  6. soporte IDE.

La única desventaja parece ser la velocidad. Creación de una matriz y que opera en él es más rápido. Sin embargo, todos sabemos que en muchos casos el tiempo de CPU es mucho más barato que el tiempo de programación. ;)

Después de pensarlo durante algún tiempo, aquí es mi propia respuesta.

Lo principal de prefiriendo objetos de valor sobre matrices es claridad .

Considere esta función:

// Yes, you can specify parameter types in PHP
function MagicFunction(Fred $fred)
{
    // ...
}

frente

function MagicFunction(array $fred)
{
}

La intención es más clara. El autor función puede cumplir su requisito.

Más importante aún, como el usuario, puedo fácilmente buscar lo que constituye un Fred válida . Sólo necesito para abrir Fred.php y descubrir su funcionamiento interno.

Hay un contrato entre la persona que llama y el destinatario de la llamada. El uso de objetos de valor, este contrato puede ser escrito como código de sintaxis verificado:

class Fred
{
    public $name;
    // ...
}

Si usara una matriz, sólo puedo esperar que mi usuario podría leer los comentarios o la documentación:

// IMPORTANT! You need to specify 'name' and 'age'
function MagicFunction(array $fred)
{
}

Dependiendo del caso de uso puede ser que utilice o. La ventaja de la clase es que puedo utilizarlo como un tipo y uso Sugerencias Tipo de métodos o cualquier método de introspección. Si sólo quiero circular algún conjunto de datos al azar de una consulta o algo, yo utilizo probable la matriz. Así que supongo que el tiempo que Fred tiene un significado especial en mi modelo, que haría uso de una clase.

En una nota:
ValueObjects se supone que son inmutables. Por lo menos si usted se refiere a la definición de Eric Evan en Domain Driven Design. En POEA de Fowler, ValueObjects no necesariamente tienen que ser inmutable (aunque se sugiere), pero no deben tener identidad, que es claramente el caso de Fred .

Permítanme plantear esta pregunta a usted:

¿Qué es tan diferente sobre la fabricación de un error tipográfico como $myFred['naem'] y hacer un error tipográfico como $myFred->naem? El mismo problema sigue existiendo en ambos casos y que tanto el error.

Me gusta usar Kiss (mantenerlo simple, estúpido) cuando programo.

  • Si simplemente devuelve un subconjunto de una consulta de un método, devuelva una matriz.
  • Si va a guardar los datos como un público protegido variables / privada / estática / en una de sus clases, que sería mejor para almacenarlo como stdClass.
  • Si va a pasar a finales de este a otro método de clase, es posible que prefiera la tipificación estricta de la clase Fred, es decir public function acceptsClass(Fred $fredObj)

Usted podría tener la misma facilidad creado una clase estándar en lugar de una matriz si es para ser utilizado como un valor de retorno. En este caso se podría importar menos tipos de datos estrictos.

$class = new stdClass();
$class->param = 'value';
$class->param2 = 'value2';
return $class;

Un profesional para el hash: Es capaz de manejar combinaciones de nombre y valor que son desconocidos en tiempo de diseño

.

Cuando el valor de retorno representa una entidad en su solicitud, se debe usar un objeto, ya que este es el propósito de la programación orientada a objetos. Si lo que desea es devolver un conjunto de valores no relacionados, entonces no es tan clara. Si es parte de una API pública, sin embargo, a continuación, una clase declarada sigue siendo el mejor camino a seguir.

Sinceramente, me gustan los dos.

  • matrices hash son mucho más rápido que hacer que los objetos, y el tiempo es dinero!
  • Pero, JSON no le gusta matrices de hash (que parece un poco como programación orientada a objetos TOC).
  • Tal vez para proyectos con varias personas, una clase bien definida, sería mejor.
  • matrices Hash podrían tomar más tiempo de CPU y la memoria (un objeto tiene una cantidad predefinida), aunque es difícil estar seguro para cada escenario.

Pero lo que realmente chupa está pensando en cuál de ellos utilizar demasiado. Como dije, JSON no le gustan los hashes. Vaya, he utilizado una matriz. Tengo que cambiar unos pocos miles de líneas de código ahora.

No me gusta, pero parece que las clases son la forma más segura de ir.

El beneficio de un valor de objeto propio es que no hay manera de hacer realidad una y otra inválida y no hay manera de cambiar lo que existe (la integridad y la "inmutabilidad"). Con sólo captadores y parámetros Tipo dando a entender los, no hay manera de meter la pata en el código compilables, que es obvio que puede hacerlo fácilmente con matrices maleables.

Si lo prefiere puede validar en un constructor público y lanzar una excepción, pero esto proporciona un método de fábrica más suave.

class Color
{
    public static function create($name, $rgb) {
        // validate both
        if ($bothValid) {
            return new self($name, $rgb);
        } else {
            return false;
        }
    }
    public function getName() { return $this->_name; }
    public function getRgb() { return $this->_rgb; }

    protected function __construct($name, $rgb)
    {
        $this->_name = $name;
        $this->_rgb = $rgb;
    }
    protected $_name;
    protected $_rgb;
}

He trabajado con POO Idiomas más de 10 años. Si usted entiende la forma en objetos de trabajo que les encantará. Herencia, polimorfismo, encapsulación, la sobrecarga son la principal ventaja de la programación orientada a objetos. Por otro lado, cuando hablamos de PHP que tenemos que tener en cuenta que PHP no es un lenguaje orientado a objetos completa destacados. Por ejemplo no podemos utilizar la sobrecarga de métodos o constructor sobrecarga (sencillo).

Las matrices asociativas en PHP es una característica muy agradable, pero creo que las aplicaciones empresariales daños php. Al escribir código que desea obtener la aplicación limpia y fácil de mantener.

Otra piensan que usted suelta con matrices asociativas es que no se puede utilizar IntelliSense.

Así que creo que si desea escribir Cleanner y el código más fácil de mantener que hay que utilizar las funciones de programación orientada a objetos cuando se proporciona.

Yo prefiero tener propiedades no modificables como en su segundo ejemplo. Siento que define con mayor claridad la estructura de clases esperado (y todas las propiedades posibles en la clase). A diferencia del primer ejemplo, que se reduce a simplemente recordando siempre utilizar los mismos nombres de las teclas. Con el segundo siempre se puede volver atrás y mirar a la clase para tener una idea de las propiedades con sólo mirar a la parte superior del archivo.

Usted sabe mejor que estás haciendo algo mal con el segundo -. Si intenta echo $this->doesntExist obtendrá un error mientras que si se intenta echo array['doesntExist'] que no lo hará

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top