Inyección de dependencia en C ++

votos
23

Esta es también una pregunta que hice en un comentario en una de las charlas de google de Miško Hevery que trataba sobre la inyección de dependencia, pero fue enterrado en los comentarios.

Me pregunto cómo puede el paso de fábrica / constructor de conectar las dependencias en conjunto puede funcionar en C ++.

Es decir, tenemos una clase A que depende de B. El constructor asignará B en el montón, pasará un puntero a B en el constructor de A mientras también asignará en el montón y devolverá un puntero a A.

¿Quién limpia después? ¿Es bueno dejar que el constructor limpie después de que esté hecho? Parece ser el método correcto, ya que en la charla dice que el constructor debe configurar objetos que se espera que tengan la misma duración o al menos las dependencias tengan una mayor duración (también tengo una pregunta sobre eso). Lo que quiero decir en código:

class builder {
public:
    builder() :
        m_ClassA(NULL),m_ClassB(NULL) {
    }
    ~builder() {
        if (m_ClassB) {
            delete m_ClassB;
        }
        if (m_ClassA) {
            delete m_ClassA;
        }
    }
    ClassA *build() {
        m_ClassB = new class B;
        m_ClassA = new class A(m_ClassB);
        return m_ClassA;
    }
};

Ahora bien, si hay una dependencia que se espera que dure más tiempo que la duración del objeto en el que lo estamos inyectando (digamos que ClassC es esa dependencia), entiendo que deberíamos cambiar el método de compilación a algo así como:

ClassA *builder::build(ClassC *classC) {
    m_ClassB = new class B;
    m_ClassA = new class A(m_ClassB, classC);
    return m_ClassA;
}

¿Cuál es tu enfoque preferido?

Publicado el 09/12/2008 a las 15:26
fuente por usuario
En otros idiomas...                            


8 respuestas

votos
13

Esta charla es sobre Java e inyección de dependencia.

En C ++ tratamos de NO pasar punteros RAW. Esto se debe a que un puntero RAW no tiene semántica de propiedad asociada. Si no tiene propiedad, entonces no sabemos quién es el responsable de limpiar el objeto.

Encuentro que la mayoría de las veces la inyección de dependencia se realiza mediante referencias en C ++.
En los casos poco comunes en los que debe usar punteros, envuélvalos en std :: unique_ptr <> o std :: shared_ptr <> según cómo desee administrar la propiedad.
En caso de que no pueda usar las características de C ++ 11, use std :: auto_ptr <> o boost :: shared_ptr <>.

También me gustaría señalar que los estilos de programación de C ++ y Java son tan divergentes que aplicar el estilo de un idioma al otro conducirá inevitablemente al desastre.

Respondida el 09/12/2008 a las 15:47
fuente por usuario

votos
9

Esto es interesante, DI en C ++ usando plantillas:

http://adam.younglogic.com/?p=146

Creo que el autor está haciendo los movimientos correctos en cuanto a no traducir Java DI en C ++ demasiado literalmente. Vale la pena leer.

Respondida el 23/12/2009 a las 02:08
fuente por usuario

votos
6

Recientemente he sido mordido por el insecto DI. Creo que resuelve muchos de los problemas de complejidad, en especial la parte automatizada. He escrito un prototipo que le permite utilizar DI de una manera bastante C ++, o al menos eso creo. Puede echar un vistazo al ejemplo de código aquí: http://codepad.org/GpOujZ79

Las cosas que están claramente ausente: no alcance, sin unión de la interfaz de la aplicación. Este último es bastante fácil de resolver, el primero, no tengo idea.

Yo estaría muy agradecido si alguien aquí tiene una opinión sobre el código.

Respondida el 10/05/2010 a las 17:39
fuente por usuario

votos
3

Usa RAII

Darle un puntero sin procesar a alguien es lo mismo que darles la propiedad. Si eso no es lo que quieres hacer, deberías darle algún tipo de fachada que también sepa cómo limpiar el objeto en cuestión.

shared_ptr <> puede hacer esto; el segundo argumento de su constructor puede ser un objeto de función que sepa cómo eliminar el objeto.

Respondida el 09/12/2008 a las 17:40
fuente por usuario

votos
2

Con base en mi propia experiencia, lo mejor es tener las reglas de propiedad claros. Para los pequeños objetos concretos, lo mejor es utilizar copia directa de evitar la dependencia cruz.

A veces, la dependencia cruz es inevitable, y no hay ninguna propiedad clara. Por ejemplo, las instancias de B (M) casos, una propia (n), y ciertos casos B pueden ser propiedad de múltiple como. En este caso, lo mejor es aplicar el recuento de referencias a B, de forma similar a la cuenta de referencias COM. Todas las funciones que toman posesión de B * deben aumentar el conteo de referencia en primer lugar, y disminuirla cuando se libera la posesión.

También evito el uso de impulso :: shared_ptr ya que crea un nuevo tipo (shared_ptr y B * convertido en dos tipos distintos). He encontrado que trae más dolores de cabeza cuando agrego métodos.

Respondida el 23/12/2009 a las 17:04
fuente por usuario

votos
2

En C ++, normalmente, cuando hace las cosas bien, no necesita escribir destructores en la mayoría de los casos. Debe usar punteros inteligentes para eliminar cosas automáticamente. Creo que el constructor no se parece al propietario de las instancias ClassA y ClassB. Si no le gusta usar punteros inteligentes, debe pensar en los objetos de por vida y sus propietarios.

Respondida el 09/12/2008 a las 16:14
fuente por usuario

votos
2

Las cosas se complican si no resuelves la cuestión de la propiedad de una vez por todas. Simplemente tendrá que decidir en su implementación si es posible que las dependencias vivan más que los objetos en los que se inyectan.

Personalmente, diría que no: el objeto al que se inyecta la dependencia se eliminará después. Tratar de hacerlo a través del generador significa que el constructor tendrá que vivir más tiempo que la dependencia y el objeto en el que se inyecta. Esto causa más problemas de los que resuelve, en mi opinión, porque el constructor no sirve para ningún propósito más útil después de que se completó la construcción con la inyección de dependencia.

Respondida el 09/12/2008 a las 15:33
fuente por usuario

votos
1

También puede comprobar la inyección FFEAD Dependencia . Proporciona DI en las líneas de primavera para Java y tiene una forma no intrusiva de hacer frente a las cosas. También tiene un montón de otras características importantes como el incorporado soporte AJAX, Reflejo, serialización, C ++ intérprete, componentes comerciales para C ++, ORM, mensajería, Web-Services, Hilo-piscinas y un servidor de aplicaciones que soporta todas estas características.

Respondida el 10/08/2010 a las 08:31
fuente por usuario

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more