Entendiendo Dependency inversion pattern (Interfaces PHP)

50 views
Skip to first unread message

David Macias Hurtado

unread,
May 21, 2018, 5:37:23 AM5/21/18
to DDD-es
Buenas, 

Estoy formándome con los principios SOLID. Y el que mas problemas me está dando, a pesar de que leo que es el mas sencillo de entender, es el principio de inversión de dependencias. Entiendo el concepto, entiendo la utilidad y finalidad, pero no comprendo la implementación con respecto a las interfaces a la hora práctica de aplicarlas.

Procedo con el ejemplo que estoy trabajando.

Tengo las siguientes entidades:

*userModel.php
-name
-sname
-email

*userInterface.php
-changeMail()

*userEntity.php extend UserModel implements userInterface

passwordModel.php,
-hash
-strenght
-type

*passwordInterface,php
-newHash()

*passwordEntity.php extend paswordModel implements passwordInterface

Bien, de forma muy genérica, esa es la estructura de mis 2 entidades.

Ahora, si yo quiero "descaragar" de mi BD, un usuario completo, en la capa de infrastructura, tendría que implentar una clase que en el constructor tuviera:

class usuarioGenerico
$user
;
$pass
;
__consrtuct
(passwordInterface $p, userInterface $u){
 $this
->user = $u;
 $this
->pass = $p;
}

Pero, mi duda es, ¿Cómo genero una instancia "final" de este objeto?

Es decir (obviando la capa de infraestructura) cuando descargo usuarios desde BD, y creo un servicio de provisión de usuarios, como tengo que instanciar este "usuario" para crear un volcado de los mismo a, por ejemplo, un array de $usuarioGenerico?

Lo que yo haría es:

usersFinal[] = new usuarioGenerico(new passwordEntity, new userEntity);

Pero no estoy seguro de estar aplicando bien los conceptos.

Alguien puede echarme una mano?
















Wilmer Arteaga

unread,
May 21, 2018, 12:20:52 PM5/21/18
to ddd...@googlegroups.com
Hola David,  la idea de la inversión de dependencia es evitar instanciar directamente clases dentro de otra clase que los utiliza.

Te dejo un ejemplo de como masomenos lo manejo yo, aplico la inversión en el controlador, posiblemente el UserModel también debería un constructor para el manejador de DB, en mi caso por ejemplo es doctrine.
Depende de como accedas a DB.
 
Espero te ayude.

Saludos.

interface UserModelInterface
{
    public function getEntity($id);
}

class UserModel implements UserModelInterface
{
    //Acá podrías tener inseccion de dependencia de tu manejador de BD
    //Depende de cómo accedas a tu DB

    public function getEntity($id)
    {
        //Acceso a la DB
    }

    public function changePassword($user, $password)
    {
        //Aplicar cambio a la entidad y guardas en DB
    }
}

class Entity
{
    private $name;

    private $sname;

    private $mail;

    private $password;

    public function setPassword($password)
    {
        $this->password = $password;
    }
}

User Controller
{
    private $userModel;

    public function __construct(UserModelInterface $userModel)
    {
        $this->userModel = $userModel;
    }

    public function viewAction()
    {

        $id = 1; //id de usuario

        //Obtener usuario de DB
        $user = $userModel->getEntity($id)

        $newPassword = "123545";
        
        //Actualizar password (forma 1)
        $user = $this->userModel->getEntity($id)
        $user->setPassword($newPassword);
        $this->userModel->save($user);

        //Actualizar password (forma 2)
        $this->userModel->changePassword($user, $newPassword) // O pasar $id en vez de user

        //Actualizar password (forma 3)
        //Usando una capa intermedia "UserService" el cuál tendra acceso a tu modelo, 
        //así evitas que tu controlador acceda a tu modelo directamente, lo uso para proyectos grandes, y donde tengas mucha lógica antes de guardar en BD.
        $this->userService->changePassword($id, $newPassword);
    }
}

--
Has recibido este mensaje porque estás suscrito al grupo "DDD-es" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a ddd-es+unsubscribe@googlegroups.com.
Para publicar en este grupo, envía un correo electrónico a ddd...@googlegroups.com.
Visita este grupo en https://groups.google.com/group/ddd-es.
Para acceder a más opciones, visita https://groups.google.com/d/optout.



--
Saludos cordiales

Wilmer Armando Arteaga Izquierdo
     wil...@yarkan.pe - 969355746

David Macias Hurtado

unread,
May 22, 2018, 4:48:52 AM5/22/18
to DDD-es
Buenas Wilmer. 

Muchas gracias por tu respuesta. Lo veo bastante claro en tu ejemplo. 

Lo que sí me doy cuenta es de las siguientes apreciaciones que deduzco tras ver tu ejemplo:
- Supongo que la class entity tendría aplicacion dentro del controlador de usuario. Es como yo lo haría. Entiendo que ha sido un olvido.
- La capa de consolidación de DB, yo la pondría inyectada en el constructor del controlador del usuario. Sería igual de correcto?
- Me doy cuenta que la implementación de las capas en esta "arquitectura" es poco marcada y libre. Es decir no hay una especificación exacta de como situar las capas y de cuantas haya entre usuario y modelo.
- Es lícito, cumpliendo con las normas DDD, la herencia de clases? (extend's) No es esta forma también de alguna forma una dependencia entre objetos?
- Y el uso de trait's?

Muchas gracias por tu ayuda. Estoy aprendiendo, y me surgen muchas dudas.

Un saludo
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a ddd-es+un...@googlegroups.com.

Para publicar en este grupo, envía un correo electrónico a ddd...@googlegroups.com.
Visita este grupo en https://groups.google.com/group/ddd-es.
Para acceder a más opciones, visita https://groups.google.com/d/optout.

Wilmer Arteaga

unread,
May 22, 2018, 1:45:42 PM5/22/18
to ddd...@googlegroups.com
Hola David.

- En cuanto a las entidades en el caso de DDD, recuerda que van dentro de la capa "dominio" y las cuales deben ser pojos, los mas limpias posibles y libres de algun framework.
  Estas entidades en realidad estarán presentes en cualquier otra capa (controladores, modelo, servicios, BD).
- En cuanto al uso de DB(normalmente llamado Repositorios en DDD o models) si podrían ir inyectarse dentro de controladores, pero si fuera mi caso, solo lo aplicaría en caso de proyectos pequeños que no necesiten muchas reglas de negocio,
  si el proyecto es grande, mejor usar una capa intermedia (en DDD sería la capa de aplicación), donde va mucho mas reglas de negocio.
- Si en cuanto a php,  tienes la libertad de armar tu estructura de carpetas de acuerdo a la arquitectura, trata de encontrar algo que refleje la arquitectura DDD, si ves bien el modelo está bien marcadas las capas (vista, aplicación, dominio, arquitectura)  lo que en php podría ser (Controladores y views, servicios, entidades  y repositorios).
- La herencia claro que se dá, en todos los niveles realmente, ya depende de uno identificar donde aplica. una clase heredada a nivel de inyección va a funcionar tal cuál una clase padre.
- Traits, es muy útil en casos que necesites reutilizar funciones que no necesariamente deban estár incluidas en una herencia.


Espero te sirva.

Saludos.


Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a ddd-es+unsubscribe@googlegroups.com.

Para publicar en este grupo, envía un correo electrónico a ddd...@googlegroups.com.
Visita este grupo en https://groups.google.com/group/ddd-es.
Para acceder a más opciones, visita https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages