php dependency-injection parameter-passing

¿Cómo puedo usar "Dependency Injection" en funciones simples de php, y debería molestarme?



dependency-injection parameter-passing (5)

He hecho muchas búsquedas sobre este tema (PHP Dependency Injection) y no he encontrado demasiado a mi gusto. Se ha escrito mucho sobre el tema para otros idiomas (Google Guice - http://code.google.com/p/google-guice/ , Java Spring), pero no pude encontrar mucho disponible para PHP. Independientemente del idioma, sin embargo, los desafíos son similares.

Las tres versiones que enumera en su pregunta son el enfoque típico. La versión 3 es la más cercana a la dirección en la que he visto funcionar la industria. Al cambiar la responsabilidad de crear sus objetos dependientes fuera de su clase, puede manipularlos como lo desee en su código de prueba. Sin embargo, el problema que encontré con ese enfoque es que terminas con largas cadenas de objetos dependientes en tu constructor que ni siquiera pueden ser utilizados por el objeto receptor, sino que pasan a través de un objeto dependiente secundario. Se pone complicado y pierdes el conocimiento de lo que viene de donde.

El ejemplo de Dependency Container de @Arkh y @mmmshuddup es un gran comienzo, pero aun así encontré limitaciones con ese enfoque. La solución final sobre la que llegué fue una solución construida a medida modelada en cierto modo según el modelo de pastel popular en Scala. Le permite pasar una única dependencia a cada uno de sus constructores Y le permite definir la construcción predeterminada de los objetos dependientes por clase. Esto lo libera de largas cadenas de dependencia y también pierde el control de las implementaciones predeterminadas de sus dependencias.

Llamé al sistema Diesel y estoy muy contento con él. Publiqué el código en github para cualquier persona interesada. Puede acceder desde el blog que escribí sobre el tema, que describe el uso básico y detalla su pregunta. http://developers.blog.box.com/2012/02/15/introducting-diesel-php-dependency-injection/

Escucho a la gente hablar sobre la inyección de dependencia y su beneficio todo el tiempo, pero realmente no lo entiendo.

Me pregunto si es una solución para el problema "Paso las conexiones de la base de datos como argumentos todo el tiempo".

Intenté leer la entrada de wikipedia, pero el ejemplo está escrito en Java, por lo que no entiendo la diferencia que está tratando de aclarar. ( http://en.wikipedia.org/wiki/Dependency_injection ).

Leí este artículo sobre dependencia-inyección-en-php ( http://www.potstuck.com/2009/01/08/php-dependency-injection/ ), y parece que el objetivo es no pasar dependencias a un objeto directamente, pero para acordonar la creación de un objeto junto con la creación de sus dependencias. Sin embargo, no estoy seguro de cómo aplicar eso en un contexto de uso de funciones de php.

Además, ¿es la siguiente Inyección de Dependencia, y debería molestarme en intentar hacer la inyección de dependencia en un contexto funcional?

Versión 1: (el tipo de código que creo, pero no me gusta, todos los días)

function get_data_from_database($database_connection){ $data = $database_connection->query(''blah''); return $data; }

Versión 2: (¿no tiene que pasar una conexión de base de datos, pero tal vez no una inyección de dependencia?)

function get_database_connection(){ static $db_connection; if($db_connection){ return $db_connection; } else { // create db_connection ... } } function get_data_from_database(){ $conn = get_database_connection(); $data = $conn->query(''blah''); return $data; } $data = get_data_from_database();

Versión 3: (la creación del "objeto" / datos está separada, y el código de la base de datos es inmóvil, ¿entonces esto podría contar como inyección de dependencia?)

function factory_of_data_set(){ static $db_connection; $data_set = null; $db_connection = get_database_connection(); $data_set = $db_connection->query(''blah''); return $data_set; } $data = factory_of_data_set();

¿Alguien tiene un buen recurso o solo una idea que hace que el método y el beneficio -crystal- sean claros?


Inyección de dependencia es la idea de eliminar la dependencia entre 2 componentes para centrarse en por qué son dependientes.

Imagine que tiene un componente A que necesita usar los servicios de otro componente B.

Si codifica la existencia de B dentro de A, entonces estará atascado cuando quiera que A use los servicios de sames, pero implementado por otro componente.

Por lo general, usted define una interfaz de servicio que B y C implementarán, y se asegura de que cuando usa A, lo alimente con objetos compatibles con la interfaz necesaria.

En su caso, podría considerar que su interfaz es un servicio en el que puede realizar una consulta.

Su primer caso es el que está más cerca de la idea de Inyección de Dependencia.


Inyección de dependencia es una gran palabra para "Tengo algunos parámetros más en mi constructor".

Es lo que hiciste antes de la terrible ola de Singleton cuando no te gustaban los globales:

<?php class User { private $_db; function __construct($db) { $this->_db = $db; } } $db = new Db(); $user = new User($db);

Ahora, el truco es usar una sola clase para administrar sus dependencias, algo así:

class DependencyContainer { private _instances = array(); private _params = array(); public function __construct($params) { $this->_params = $params; } public function getDb() { if (empty($this->_instances[''db'']) || !is_a($this->_instances[''db''], ''PDO'') ) { $this->_instances[''db''] = new PDO( $this->_params[''dsn''], $this->_params[''dbUser''], $this->_params[''dbPwd''] ); } return $this->_instances[''db'']; } } class User { private $_db; public function __construct(DependencyContainer $di) { $this->_db = $di->getDb(); } } $dependencies = new DependencyContainer($someParams); $user = new User($dependencies);

Debe pensar que es solo otra clase y más complejidad. Sin embargo, su clase de usuario puede necesitar algo para registrar mensajes como muchas otras clases. Simplemente agregue una función getMessageHandler a su contenedor de dependencias, y algunos $this->_messages = $di->getMessageHandler() a su clase de usuario. Nada para cambiar en el resto de tu código.

Obtendrás mucha información sobre el documento de Symfony


Ninguno de sus ejemplos se parece a la inyección de dependencia, sin embargo, la versión uno es la más cercana. La inyección de dependencia es una técnica utilizada en la programación orientada a objetos, donde el constructor de un objeto tiene argumentos para los objetos de servicio que necesita, y los objetos de servicio son pasados ​​por el creador de la instancia (que podría ser una fábrica, una prueba o un marco de inyección de dependencia).

Para evitar su problema de "pasar siempre el objeto de conexión", puede considerar el patrón de plantilla. El patrón de plantilla es básicamente una clase base abstracta con la parte común de un bloque de código repetido, y métodos abstractos para permitir la variación entre las instancias de esos bloques de código repetidos. Básicamente, la base es una plantilla de un bloque de código, y los métodos abstractos son los espacios en blanco que deben rellenarse. Personalmente utilizo el patrón de método de plantilla para hacer mi control de recursos de base de datos en Java.