¿Es una mala práctica pasar instancias a través de varias capas?

59

En el diseño de mi programa, a menudo llego al punto en el que tengo que pasar instancias de objetos a través de varias clases. Por ejemplo, si tengo un controlador que carga un archivo de audio, y luego se lo pasa a un jugador, y el jugador se lo pasa al reproductor, que se puede pasar de nuevo a otro lugar, etc. Parece algo malo, pero no lo hago. saber como evitarlo. ¿O está bien hacer esto?

EDITAR: Tal vez el ejemplo del reproductor no sea el mejor porque podría cargar el archivo más tarde, pero en otros casos no funciona.

    
pregunta Puckl 27.09.2012 - 14:32

12 respuestas

54

Como han mencionado otros, esto no es necesariamente una mala práctica, pero debe prestar atención a que no está rompiendo la separación de preocupaciones de las capas y pasando instancias específicas de capas entre capas. Por ejemplo:

  • Los objetos de la base de datos nunca deben pasar a capas superiores. He visto programas que utilizan la clase DataAdapter de .NET, un DB- acceda a la clase y pásela a la capa UI, en lugar de usar el DataAdapter en el DAL, crear un DTO o conjunto de datos y pasarlo. El acceso a la base de datos es el dominio del DAL.
  • Los objetos de la interfaz de usuario deben, por supuesto, estar limitados a la capa de la interfaz de usuario. Una vez más, he visto esto violado, tanto con ListBoxes rellenados con los datos del usuario pasados a la capa BL, en lugar de una matriz / DTO de su contenido, y (una de mis favoritas en particular), una clase DAL que recuperó datos jerárquicos de La base de datos, y en lugar de devolver una estructura de datos jerárquica, simplemente creó y rellenó un objeto TreeView y lo devolvió a la interfaz de usuario para agregarlo dinámicamente a un formulario.

Sin embargo, si las instancias que está pasando son los DTO o las entidades, es probable que esté bien.

    
respondido por el Avner Shahar-Kashtan 27.09.2012 - 15:10
15

Es interesante que nadie haya hablado de objetos inmutables todavía. Yo diría que pasar un objeto inmutable a través de las distintas capas es realmente una cosa buena en lugar de crear muchos objetos de corta duración para cada capa.

Hay algunas grandes discusiones sobre la inmutabilidad de Eric Lippert en su blog

Por otro lado, argumentaría que el paso de objetos mutables entre capas es un diseño malo . Básicamente, estás construyendo una capa con la promesa de que las capas circundantes no la alterarán de manera que rompa tu código.

    
respondido por el M Afifi 27.09.2012 - 18:12
13

Pasar las instancias de objetos es algo normal. Reduce la necesidad de mantener el estado (es decir, las variables de instancia) y desacopla el código de su contexto de ejecución.

Uno de los problemas que puede enfrentar es la refactorización, cuando debe cambiar las firmas de varios métodos a lo largo de la cadena de invocación en respuesta a los requisitos de parámetros cambiantes de un método cerca del final de esa cadena. Sin embargo, se puede mitigar con el uso de herramientas modernas de desarrollo de software que ayudan en la refactorización.

    
respondido por el dasblinkenlight 27.09.2012 - 14:49
8

Tal vez menor, pero existe el riesgo de asignar esta referencia en algún lugar de una de las capas, lo que podría causar una referencia colgante o una pérdida de memoria más adelante ...

    
respondido por el techfoobar 27.09.2012 - 14:59
7

Si está pasando objetos simplemente porque es necesario en un área remota de su código, utilice la inversión de control y los patrones de diseño de inyección de dependencia junto con un contenedor IoC apropiado pueden resolver los problemas relacionados con la carga de instancias de objetos. Lo he usado en un proyecto de tamaño mediano y nunca más consideraría escribir una gran pieza de código de servidor sin usarlo.

    
respondido por el Steven Schlansker 27.09.2012 - 19:28
4

Pasar datos a través de un grupo de capas no es algo malo, es realmente la única forma en que un sistema en capas puede funcionar sin violar la estructura en capas. La señal de que hay problemas es cuando pasas tus datos a varios objetos en la misma capa para lograr tu objetivo.

    
respondido por el Ryathal 27.09.2012 - 14:48
3

Respuesta rápida: No hay nada de malo en pasar instancias de objetos. Como también se mencionó, el punto es omitir la asignación de esta referencia en todas las capas que pueden causar una referencia colgante o pérdidas de memoria.

En nuestros proyectos, utilizamos esta práctica para pasar DTO (objeto de transferencia de datos) Entre capas y es una práctica muy útil. También reutilizamos nuestros objetos dto para construir más complejos una vez, como para información de resumen.

    
respondido por el EL Yusubov 27.09.2012 - 15:27
3

Principalmente soy un desarrollador de interfaz de usuario web, pero me parece que su incomodidad intuitiva puede deberse menos a la transferencia de la instancia y más al hecho de que va un poco de procedimiento con ese controlador. ¿Debería su controlador estar sudando todos estos detalles? ¿Por qué incluso hace referencia a más de un nombre de otro objeto para reproducir audio?

En el diseño de POO, tiendo a pensar en términos de lo que es siempre verde y lo que es más probable que esté sujeto a cambios. El tema para cambiar cosas es lo que querrá colocar en sus cajas de objetos más grandes para que pueda mantener interfaces consistentes incluso cuando los jugadores cambian o se agregan nuevas opciones. O te encuentras con ganas de intercambiar objetos de audio o componentes al por mayor.

En este caso, su controlador debe identificar que existe la necesidad de reproducir un archivo de audio y luego tener una forma consistente / siempre verde de reproducirlo. El reproductor de audio, por otro lado, podría cambiar fácilmente a medida que la tecnología y las plataformas se alteren o se agreguen nuevas opciones. Todos esos detalles deberían estar debajo de la interfaz de un objeto compuesto más grande, IMO, y no debería tener que volver a escribir su controlador cuando cambian los detalles de cómo se reproduce el audio. Luego, cuando pasa una instancia de objeto con detalles como la ubicación del archivo en el objeto más grande, todo ese intercambio se realiza en el interior de un contexto apropiado donde es menos probable que alguien haga algo tonto con él.

Entonces, en este caso, no creo que la instancia de objeto que se está lanzando sea lo que te esté molestando. Es que el Capitán Picard está corriendo hacia la sala de máquinas para encender el núcleo de urdimbre, corriendo hacia el puente para trazar las coordenadas, y luego presiona el botón "punch-it" después de encender los escudos en lugar de simplemente decir "Toma nosotros al planeta X en Warp 9. Hazlo así ". y dejando que su tripulación resuelva los detalles. Porque cuando lo maneja de esa manera, puede ser el capitán de cualquier nave de la flota sin saber el diseño de cada nave y cómo funciona todo. Y esa es, en última instancia, la mayor victoria de diseño OOP a la que se puede disparar, IMO.

    
respondido por el Erik Reppen 28.09.2012 - 03:00
2

Es un diseño bastante común que termina apareciendo, aunque es posible que tengas problemas de latencia si tu aplicación es sensible a ese tipo de cosas.

    
respondido por el James 27.09.2012 - 14:53
2

Este problema se puede resolver con variables de alcance dinámico, si su idioma las tiene, o almacenamiento de subprocesos locales. Estos mecanismos nos permiten asociar algunas variables personalizadas con una cadena de activación o un hilo de control, para que no tengamos que pasar estos valores al código que no tiene nada que ver con ellos solo para que puedan comunicarse a otro código. que los necesita

    
respondido por el Kaz 27.09.2012 - 19:48
2

Como han señalado las otras respuestas, este no es un diseño intrínsecamente deficiente. Puede crear un acoplamiento estrecho entre las clases anidadas y las que las anidan, pero aflojar el acoplamiento puede no ser una opción válida si anidar las referencias proporciona un valor al diseño.

Una posible solución es "aplanar" las referencias anidadas en la clase del controlador.

En lugar de pasar un parámetro varias veces a través de objetos anidados, puede mantener en la clase de controlador las referencias a todos los objetos anidados.

La forma exacta en que se implementa esto (o si es una solución válida) depende del diseño actual del sistema, como:

  • ¿Puede mantener algún tipo de mapa de los objetos anidados en el controlador sin que se complique demasiado?
  • Cuando pasa el parámetro al objeto anidado apropiado, ¿puede el objeto anidado reconocer el parámetro inmediatamente, o se produjo una funcionalidad adicional al pasarlo a través de los objetos anidados?
  • etc.

Este es un problema que encontré en un patrón de diseño MVC para un cliente GXT. Nuestros componentes de GUI contenían componentes de GUI anidados para varias capas. Cuando se actualizaron los datos del modelo, terminamos de pasarlos a través de varias capas hasta que alcanzaron los componentes adecuados. Creó un acoplamiento no deseado entre los componentes de la GUI porque si queríamos que una nueva clase de componentes de la GUI aceptara los datos del modelo, tuvimos que crear métodos para actualizar los datos del modelo en todos los componentes de la GUI que contenían la nueva clase.

Para solucionarlo, mantuvimos en la clase de Vista un mapa de referencias a todos los componentes de la GUI anidados, de modo que cada vez que se actualizaran los datos del modelo, la Vista podría enviar los datos del modelo actualizados directamente a los componentes de la GUI que lo necesitaban, fin de la historia. Esto funcionó bien porque solo había instancias individuales de cada componente GUI. Pude ver que no funciona tan bien si hubiera varias instancias de algunos componentes de la GUI, lo que dificulta la identificación de la copia que se necesita actualizar.

    
respondido por el David Kaczynski 08.10.2012 - 03:10
0

Lo que estás describiendo es un patrón de diseño denominado Chain Of Responsibility .  Apple usa este patrón para su sistema de manejo de eventos, por lo que vale la pena.

    
respondido por el user8865 27.09.2012 - 23:16

Lea otras preguntas en las etiquetas