¿Debería el uso de DI / IoC eliminar todas las apariciones de la palabra clave "nueva"?

21

¿Debería el uso de la inyección de dependencia y un contenedor de inversión de control eliminar todas las apariciones de la newpalabra clave " " de su código?

En otras palabras, ¿debería cada objeto / dependencia, sin importar cuán simple o de corta duración, ser "registrado" dentro de su contenedor IoC e inyectado en el método / clase que necesita usarlos?

Si no, ¿dónde dibuja la línea entre las dependencias / objetos que se registran en el contenedor IoC, frente a lo que se crea "en línea" como referencia concreta, a través de la newpalabra clave?

CraigTP
fuente
He tenido el mismo pensamiento, en la línea de "¿es 'nuevo' una palabra de 4 letras?"
Michael Easter

Respuestas:

27

Evita el dogma. Haz lo que se siente bien.

Prefiero usar "nuevo" para estructuras de datos que no tienen comportamiento.

Si la clase tiene comportamiento, entonces miro el alcance de ese comportamiento. Si no tiene estado y no tiene dependencias, me inclino hacia "nuevo". Solo comienzo a refactorizar hacia DI cuando necesito agregar una dependencia a recursos con estado (como una base de datos o un archivo), o a otras clases con tales recursos.

Alex Beynenson
fuente
15
+1 para "evitar el dogma". Demasiado fácil caer en la trampa de simplemente seguir los movimientos sin comprender lo que está sucediendo o dónde debe usarse correctamente.
Wayne Molina
@Alex me gusta esto. Un enfoque muy pragmático. Curiosamente, iba a agregar un código en mi pregunta que mostraba una newdependencia ed en mi propio código que provocó mi pregunta. Era una clase simple sin funcionalidad o "comportamiento" per se, solo propiedades simples.
CraigTP
11

En mi libro , presento la distinción entre dependencias estables y volátiles . Es muy importante usar DI con dependencias volátiles, pero a menudo puede lograr un acoplamiento aún más suelto al abstraer e inyectar dependencias estables.

Tenga en cuenta que la aplicación de DI no debe depender de un contenedor DI . En el caso de que se use la DI de Poor Man , no newse eliminan las palabras clave, solo se mueven a la raíz de composición .

Algunas personas prefieren la DI de Poor Man a los contenedores de DI. El costo de mantenimiento puede ser mayor, pero a cambio obtienes seguridad en tiempo de compilación. Como escuché recientemente a Dan North decir: " newes lo nuevo new" :)

Lo que se quiere decir con esto es simplemente que, en lugar de implementar la raíz de composición con un contenedor DI, solo contendría un montón de newdeclaraciones anidadas .

Mark Seemann
fuente
Mark, para ampliar un poco mi comentario de Twitter , Programmers es el lugar adecuado para preguntas conceptuales y de pizarra que no se ocupan de un error específico en una implementación.
Adam Lear
3
Stack Overflow tiene más de 2000 preguntas en la etiqueta de inyección de dependencia, y muchas de ellas son como esta. Los programadores tienen 23 preguntas en la misma etiqueta. Según estos números, ¿a dónde debe ir un desarrollador para tener la mayor posibilidad de obtener una respuesta a una pregunta como esta?
Mark Seemann
1
Muchas de esas preguntas son anteriores a los programadores por completo. Este sitio fue creado para quitar preguntas conceptuales de SO y darles un hogar dedicado. Y todavía estamos creciendo. Es un trabajo en progreso, pero idealmente las preguntas que no involucran problemas de implementación específicos se migrarían aquí. Hacemos lo que podamos mientras tanto.
Adam Lear
3

"nuevo" no es una palabra clave prohibida. Mis reglas personales:

Todos los "servicios" (llamo a un servicio una clase diseñada para proporcionar uno o más métodos relacionados con una y solo una cosa; por ejemplo: acceder a la base de datos, recuperar / actualizar datos relacionados con un dominio dado) están registrados en el contenedor de COI. Ninguna clase debería tomar la decisión sobre cómo obtener la implementación de un servicio dado que necesita usar. Por lo tanto, siempre que necesite utilizar un servicio existente, debe configurar su clase y el contenedor IOC para que se lo proporcione. Imagine que no sabe cómo funciona su implementación, podría ser un servicio web, no le importa.

Todos los beans o modelos deben crearse con la palabra clave "nueva" o con una fábrica registrada por el COI cuando necesito que tengan algunas propiedades predeterminadas habilitadas. También está el caso particular de las clases de utilidad que contienen solo métodos estáticos (por ejemplo: un servicio de utilidad matemático). Si son totalmente independientes y no necesitan ninguna conexión a la base de datos u otro servicio registrado por el COI, los dejo fuera del COI y se los llamará estáticamente. Sin embargo, si una de esas clases necesita usar un servicio registrado con IOC existente, lo cambio a una clase singleton y lo registro en el IOC.

Jalayn
fuente
2

Solo me gustaría agregar a las respuestas existentes que se mencionaron anteriormente, newestá perfectamente bien crear objetos que sean objetos de valor puro (es decir, que solo tengan propiedades / captadores / establecedores). Vea el Blog de Google Testing para más detalles.

Jack
fuente
+1 para el enlace. Punto 9 en que la entrada de blog responde a la pregunta y proporciona una distinción pragmática entre lo que debe y no debe ser new'ed
CraigTP
1

Claramente depende del idioma que uses. Si su lenguaje lo obliga a usar objetos para representar tanto el objeto real como los registros (objeto de valor, estructuras), entonces la respuesta es probablemente no.

Hablando exclusivamente de objetos "reales", no hay nada de malo en crear una instancia explícitamente. Sin embargo, debe tener en cuenta que todas las clases deben seguir el principio de responsabilidad única. No debería ser responsabilidad de una clase elegir el implementador de un servicio en el que se basa. Sin embargo, hay clases que tienen esa responsabilidad, es decir, proporcionar implementadores de ciertos servicios. Un IoC podría ser tal clase. De hecho, cualquier tipo de fábrica es tal clase.

Para resumir: solo esas clases deberían instanciar objetos directamente, quién es la responsabilidad de elegir qué clases instanciar.
Puede encontrar útiles estos criterios: http://en.wikipedia.org/wiki/GRASP_(object-oriented_design)#Creator

back2dos
fuente
1

Una palabra: no.

Más palabras: la inyección de dependencia es exactamente eso. Es un medio por el cual introduce recursos de los que depende otro objeto, pero no debe conocer los detalles intrincados de otra fuente. Usar DI no significa que NADA en su programa deba saber cómo crear cualquier otro objeto; de hecho, considero que es altamente inviable que un programa no trivial evite por completo la "nueva" palabra clave (o alternativas basadas en la reflexión). Sin embargo, DI significa que los objetos que no deberían TENER que saber cómo crear objetos complejos que requieren muchas dependencias que acoplarán estrechamente este objeto con el otro, no deberían tener todo este conocimiento estrechamente acoplado.

Estudiaría las dos principales teorías del diseño de software de O / O, GRASP y SOLID. GRASP le dirá que estudie el propósito del objeto y se preguntará: "¿Debería este objeto ser responsable de crear nuevos objetos de este otro tipo? ¿Es eso parte de la 'descripción del trabajo' de este objeto?" SOLID va un paso más allá: la "S" representa el "Principio de responsabilidad única", que establece inequívocamente que un objeto debe tener un trabajo, y debe ser el único objeto en el programa que hace ese trabajo específico.

Por lo tanto, GRASP generalmente lo alentaría a que revise sus clases existentes para las que crea estos nuevos objetos, y encuentre uno para el cual la tarea de crear este objeto se ajuste a lo que el objeto ya hace, mientras mantiene el nivel deseado de "cohesión". SOLID le dirá que la cohesión es clave; La tarea de crear estos objetos debe asignarse a alguna fábrica que debe inyectarse en su clase. Creo que descubrirá, a medida que la complejidad de su programa continúa creciendo, que el cumplimiento de cualquiera de estas metodologías, con la voluntad de refactorizar, dará como resultado arquitecturas muy similares.

KeithS
fuente