Recientemente comencé a leer acerca de la inyección de dependencia y me ha hecho repensar algunos de mis diseños.PHP Objetos de carga diferida e inyección de dependencia
El problema que tengo es algo como esto: Digamos que tengo dos clases: Coche y Pasajero; Para esas dos clases Tengo algunos creadores de mapas de datos para trabajar con la base de datos: CarDataMapper y PassengerDataMapper
Quiero ser capaz de hacer algo como esto en código:
$car = CarDataMapper->getCarById(23); // returns the car object
foreach($car->getPassengers() as $passenger){ // returns all passengers of that car
$passenger->doSomething();
}
Antes de saber nada acerca de DI, me gustaría construir mis clases de la siguiente manera:
class Car {
private $_id;
private $_passengers = null;
public function getPassengers(){
if($this->_passengers === null){
$passengerDataMapper = new PassengerDataMapper;
$passengers = $passengerDataMapper->getPassengersByCarId($this->getId());
$this->setPassengers($passengers);
}
return $this->_passengers;
}
}
me gustaría también tienen un código similar en el método de pasajeros transportados> getCar() para buscar el coche que el pasajero se encuentra en
.Ahora entiendo que esto crea dependencias (bueno, también lo entendí antes, pero no sabía que esto es "incorrecto") entre los objetos del Automóvil y del Pasajero y los objetos del asignador de datos.
Al tratar de pensar en la solución de estas dos opciones de vino a la mente, pero no me gusta ninguno de ellos:
1: Hacer algo como esto:
$car = $carDataMapper->getCarById(23);
$passengers = $passengerDataMapper->getPassengersByCarId($car->getId());
$car->setPassengers($passengers);
foreach($car->getPassengers() as $passenger){
$passenger->doSomething();
}
Pero lo si los pasajeros tienen objetos que necesitan inyectar, y qué pasa si el anidamiento va a diez o veinte niveles ... terminaría la creación de instancias de casi todos los objetos al inicio de mi aplicación, lo que a su vez consultaría toda la base de datos durante el proceso. Si tengo que enviar al pasajero a otro objeto que tiene que hacer algo con los objetos que tiene el pasajero, no quiero instanciar inmediatamente estos objetos también.
2: La inyección de los creadores de mapas de datos en los objetos de automóviles y pasajeros y tener algo como esto:
class Car {
private $_id;
private $_passengers = null;
private $_dataMapper = null;
public function __construct($dataMapper){
$this->setDataMapper($dataMapper);
}
public function getPassengers(){
if($this->_passengers === null && $this->_dataMapper instanceof PassengerDataMapper){
$passengers = $this->_dataMapper->getPassengersByCarId($this->getId());
$this->setPassengers($passengers);
}
return $this->_passengers;
}
}
No me gusta esta mejor, ya que no es como el coche es realmente conscientes del asignador de datos, y sin el mapeador de datos, el auto podría comportarse de manera impredecible (no devolver pasajeros, cuando realmente los tiene)
Así que mi primera pregunta es: ¿Estoy tomando un enfoque completamente erróneo aquí, porque, cuanto más lo miro? , cuanto más parece que estoy construyendo un ORM, en lugar de una capa de negocios?
La segunda pregunta es: ¿Hay alguna manera de desacoplar realmente los objetos y los correladores de datos de una manera que me permita usar los objetos como se describe en el primer bloque de códigos?
Tercera pregunta: ¿ he visto algunas respuestas para otros idiomas (alguna versión de C, creo) la solución de este problema con algo como esto se describe aquí: What is the proper way to inject a data access dependency for lazy loading? Como no he tenido tiempo para jugar con otra idiomas, esto no tiene sentido para mí, así que estaría agradecido si alguien explicara los ejemplos en el enlace en PHP-ish.
También he mirado algunos marcos DI, y he leído sobre DI Containers e Inversion of Control, pero por lo que entendí se usan para definir e insertar dependencias para clases 'no dinámicas', donde por ejemplo, el Auto dependa del motor, pero no necesitaría que el motor se cargue dinámicamente desde el DB, simplemente se crearía una instancia y se inyectaría en el automóvil.
Perdón por la larga publicación y gracias de antemano.
Es posible que desee realizar la compra [PoEAA] (http://www.amazon.com/Patterns-Enterprise-Application-Architecture-Martin/dp/0321127420/ref=sr_1_1?ie=UTF8&qid=1350785602&sr=8-1&keywords= patrones + de + empresa + aplicación + arquitectura) Aunque no ayudará en absoluto con [DI] (http://martinfowler.com/articles/injection.html) (es anterior a lo común) se dará cuenta de que incluso con su Business Layer necesitarás un ORM que se encuentre debajo de él. Se recomienda un [Data Mapper] (http://martinfowler.com/eaaCatalog/dataMapper.html). +1 por hacer la pregunta que he estado buscando. – xenoterracide
Gracias por el consejo.Recientemente he estado usando Doctrine2 en la mayoría de mis proyectos, que es un ORM de Data Mapper, y me resulta bastante fácil trabajar con él. – Pinetree