2010-01-13 10 views
5

ACTUALIZADA:Controller <-> Servicio componente interacción

I tiene una aplicación de escritorio, con los siguientes componentes que interactúan:

  • Winforms UI.
  • Servicio (clase de C# en proceso que contiene lógica comercial para realmente hacer cosas).
  • Controlador (clase C# que coordina eventos generados por la IU y llama a los métodos de servicio).

Si un controlador pide un servicio para hacer algo, pero que el servicio necesita algo más desde el primer controlador (es decir, datos que el controlador debe utilizar una interfaz de usuario para obtener del usuario), cómo debe el servicio de obtener la controlador para hacerlo?


estoy cómodo con el concepto de que

  • usuario se comunica con
  • interfaz de usuario que se comunica con
  • controlador que se comunica con
  • componente de servicio (que no debe confundirse con las un servicio web o servicio fuera de proceso) que se comunica con
  • Data/Reposi tories que comm ...

y así sucesivamente.

Sin embargo, con respecto al controlador que se comunica con el servicio, ¿qué método es mejor para esto? ¿Debería:

  1. Los métodos de servicio pueden ser bastante precisos, y arrojar excepciones si algo no está bien para que el controlador sepa si seguir adelante o decirle al usuario que algo salió mal? O ...
  2. Los métodos de servicio devuelven objetos que el controlador puede inspeccionar para decidir qué hacer a continuación?

Me gusta la primera opción, porque la segunda podría significar explosión de clase, donde necesita una clase de estilo ServiceResult para cada método de servicio.

Pregunto porque, por supuesto, el componente del Servicio no puede decirle a la UI qué hacer, solo el controlador puede, pero el controlador no sabe qué decirle a la IU sin obtener retroalimentación del Servicio.

¿Qué opinas?

Respuesta

2

Su mejor opción es probablemente utilizar un modelo de evento o delegado, por ejemplo, el controlador se suscribe a un evento 'necesita más información' y muestra el formulario apropiado. La devolución de los datos adicionales al servicio se puede hacer de diferentes maneras, pero dependerá en gran medida de las características específicas de su diseño (p. Ej., Son servicios sin estado, etc.)

¿Ha escrito pruebas de unidad para su servicio? De lo contrario, este proceso probablemente lo ayudará a aclarar lo que desea de su diseño.

2

Lo primero que debe tener en cuenta al diseñar la capa/clases de servicio es hacer que sean altamente reutilizables. Deben ser objetos de servicio atómico que puedan servir no solo a su controlador, sino también a cualquier otro cliente en el futuro.

Hay algunas preguntas aquí:

  1. ¿Cómo encontrar el controlador del servicio?
    Si desea tener objetos de servicio altamente reutilizables, extensibles y ..., la dependencia entre su controlador y las clases de servicio debe estar flojamente acoplada. Evite cualquier técnica de acoplamiento ajustado. En su lugar, intente con inject la clase de servicio a su controlador (usando un contenedor IOC) y también puede usar Service Locator Design Pattern.

  2. ¿Cómo comunicar con el servicio?
    Bueno, depende del tamaño de su aplicación. Puede optar por las tecnologías de servicios empresariales, como los servicios web, simplemente use los servicios de aplicaciones. Basado en eso, usted define el protocolo entre el controlador y el servicio.

  3. ¿Qué datos debe devolver el servicio al controlador?
    Recuerde que la capa de servicio no debe saber nada sobre la navegación de la IU. Es responsabilidad del controlador decidir a dónde ir y qué hacer en función de la respuesta del objeto de servicio. ¿Por qué? Imagine que esta clase de servicio necesita ser utilizada para otra interfaz de usuario (digamos de web a flex, silverlight o aplicación de escritorio). Si agrega lógica de navegación (como un ejemplo extremo, lógica de UI/formateo) en la clase de servicio, no será reutilizable para otro sistema de IU y tampoco será reutilizable para otras clases de servicio y controladores dentro de la misma aplicación .

En pocas palabras, intente mantener la clase de servicio limpia de cualquier lógica de navegación. El controlador realmente está diseñado para ese propósito.

+0

El controlador recibe el servicio a través de un contenedor IoC. El truco es que a veces los servicios no pueden ir más allá porque necesitan más información, pero no pueden acceder a la interfaz de usuario, necesita el controlador para hacerlo. Entonces, ¿cómo debe el servicio informar al controlador que necesita reunir más información? –

+1

Si considera el servicio como un componente completo e independiente con cierta responsabilidad (solo me recuerda al CRC), puede tener un escenario principal (exitoso) y algunas excepciones (escenarios alternativos). En este caso, estás hablando de las excepciones. Esta es una opinión de alto nivel. Ahora para la implementación, me gusta usar excepciones es una forma elegante. Se explican por sí mismos y se manejan muy bien cuando se usan correctamente en las aplicaciones. Incluso si cambia su controlador o tiene otros clientes para sus servicios, todavía funcionará. Espero que esta sea la respuesta a tu pregunta. –

0

Ver mi pregunta here

Hay algunos detalles que faltan a una mejor respuesta que pregunta:

¿Es una web o un escenario de escritorio?

Si es de escritorio, ¿es un escenario desconectado? (por ejemplo, cliente rico con servicios remotos) o el cliente y el servicio en la misma máquina?

Si web - ¿es una aplicación clásica de la web 1.0? (la vista se crea como una página) o un cliente rico? (AJAX, Flex, SilverLight) donde el controlador a veces puede estar en el cliente? (Flex)

Todo esto puede afectar significativamente las decisiones.

Por cierto ¿omitiste el modelo a propósito?

+0

Escritorio - ver la actualización de la pregunta. Esto es todo en proceso: "servicio" en este contexto significa un objeto de servicio que contiene lógica comercial: el modelo utiliza el modelo para realizar el trabajo real, pero la interacción entre el controlador y el servicio es lo que realmente me interesa. en. –

0

Trabajo mucho con MVC (aunque el mío es el sabor de la aplicación web Java), y a menudo me he tropezado con algunas situaciones en las que parece que el servicio necesita interactuar de alguna manera con el controlador. Pero en todos los casos, resultó que he estado haciendo algo mal en el controlador o que la interfaz de mi servicio no es lo suficientemente flexible (es decir, de grano fino).

Cuando el servicio no recibe suficientes datos, ¿se debe a que el usuario proporciona una entrada no válida? Si es así, entonces el controlador debe realizar la validación en la entrada y mostrar el aviso o mensaje de error apropiado.

Si se espera que el usuario no proporcione todos los datos a la vez, entonces el controlador debe saber que el servicio no aceptará los datos tal como están. Por lo tanto, el controlador debe gestionar la conversación con el usuario a través de la interfaz de usuario, y finalmente pasar todo al servicio al final.

O tal vez el controlador necesita consultar el servicio durante todo el flujo del asistente. En ese caso, la interfaz del servicio probablemente debería ser más refinada.

Me gustaría ir con la opción n º 1 que ha propuesto. Si el controlador es capaz de recopilar todas las entradas requeridas desde la interfaz de usuario y proporcionarlas al servicio, pero no lo hace, el servicio debe emitir una excepción. Usar una excepción es sensato porque está tratando de pasar datos inválidos al servicio. (Esto no cambia el hecho de que no deben lanzarse excepciones para controlar el flujo del programa, sino más bien para indicar que el controlador realmente se equivocó al dar al servicio algunos datos inválidos.)

0

¿Ha considerado usar el Model View Presenter?

Sus vistas de IU implementarían interfaces, y sus interfaces conocerían estas interfaces. De esta forma, sus servicios podrían llamar a la IU para solicitar más información para llevar a cabo sus tareas. Este es un tipo de dependency inversion (pdf).