2010-10-22 19 views
5

Estoy construyendo una aplicación que es multilingüe, multi-timezoned y n-tier. Todas las fechas se almacenan en la base de datos en UTC y todos los objetos del modelo se rellenan con horas UTC. Sin embargo, los tiempos UTC nunca se muestran (a menos que el usuario tenga su zona horaria configurada en UTC).¿Dónde debe realizarse la conversión de valores de presentación en arquitectura de varios niveles?

Esto significa que necesito convertir las propiedades de tiempo en la zona horaria del usuario correcta repetitivamente. La repetición es siempre el signo de un código incorrecto o una mejor manera, así que estaba tratando de encontrar la mejor estrategia para implementar. Aunque esta es una lógica de presentación efectiva, mis pensamientos han sido variados porque parece que el modelo debería conocer los valores correctos para el usuario actual. Hasta ahora mis pensamientos son:

  1. Utilice una clase de ayudante estático y luego llámelo cada vez que se use la propiedad del modelo. Esto parece propenso al error o al olvido, y hace que los cálculos sean engorrosos.

  2. Envuelva el objeto modelo en un objeto viewmodel. Esto es igualmente engorroso especialmente cuando se trata de listas de objetos.

  3. Escriba un método de extensión para el modelo que existe solo en la capa de presentación. Esto parece más limpio pero no intuitivo.

  4. Cree una interfaz en la capa modelo para la conversión. Implementa el ayudante en la capa de presentación y dale a la capa del modelo la implementación. El modelo tiene propiedades que usan la interfaz para convertir la hora. Parece que debería estar rompiendo la separación de las preocupaciones, pero parece que no. Si tuviera un convertidor predeterminado, entonces no tendría que preocuparse por obtener excepciones de objetos nulos, sin embargo, la capa del modelo (actualmente POCO) necesitaría un contenedor para el asistente de conversión que parece desordenado.

  5. Cree una conversión al método de zona horaria local en el modelo y pase en la zona horaria actual.

Me interesan las opiniones sobre estas estrategias o cualquier otra que debería o podría estar utilizando en lugar de estas.

actualización Lo que he hecho actualmente es crear un ITimeConvertor y un ITimeConvertorFactory dentro de la capa del modelo. Luego creé implementaciones predeterminadas de estos que simplemente devuelven el valor de fecha original. Dentro de la capa del modelo, he agregado propiedades de tiempo local para cada propiedad UTC existente que estaba originalmente en el modelo. Dentro de estas propiedades utilizo la fábrica para obtener un convertidor y convertir el valor UTC en cada sentido en getter y setter. He tenido que agregar una clase de configuración estática en la capa de modelo (que realmente no me gusta) como un lugar para almacenar la fábrica actual de timeconvertors. En la parte de la aplicación web, implemento ITimeConvertorFactory y ITimeConvertor como WebTimeConvertorFactory y WebTimeConvertor. El WebTimeConvertor conoce la sesión y el usuario actual, de modo que puede captar la zona horaria actual. WebTimeConvertorFactory crea WebTimeConvertors. Cuando se inicia la aplicación (application_onstart en global.asax) creo la fábrica y la paso a la propiedad de configuración estática de la capa de modelo. Esto permite que mi capa de modelo pueda convertir las horas locales, mientras que la capa de datos solo conoce las propiedades de fecha UTC. También significa que puedo pasar localtimes directamente en el modelo y convertirlo con precisión siempre que la aplicación de consumo haya proporcionado una fábrica de convertidores. Como las propiedades UTC no se modifican, aún se pueden usar en cualquier lugar dentro de la aplicación. Aunque parecía una gran cantidad de código, encontré esta solución bastante limpia una vez implementada, ya que permite a otros consumidores del servicio implementar su conversión de tiempo de cualquier forma que quieran (si es que lo hace) manteniendo el consumo de las propiedades del modelo razonablemente obvio.

Todavía estoy abierto a mejores soluciones y críticas de mi solución actual.

Respuesta

2

Supongo que es la capa de su modelo que conoce la zona horaria del usuario, por lo que depende de la capa del modelo convertir las propiedades de tiempo. De lo contrario, debería dejar que la capa de presentación conozca la zona horaria y convertir allí el valor de cada vez.

Convertir los valores de tiempo en la capa del modelo permitiría usarlos en la capa de presentación sin conversiones, por lo que creo que sería limpio. Por ejemplo, puede inicializar sus objetos (POCO) con tiempos convertidos al principio. Pero tenga cuidado de volver a convertirlos en el modelo, olvidando que ya se han inicializado a los tiempos locales. Además, si el usuario puede editar los valores de tiempo, deberá volver a convertirlos a horas UTC antes de guardar.

Actualización: Después de un poco más de pensamiento, deduzco que la hora UTC es parte del modelo y localtimes son una vista de este modelo, por lo que el deber de conversión pertenece más en la capa de presentación (a expensas de no estar de acuerdo con las mí mismo). Con el mismo proceso de pensamiento, tener propiedades de tiempo local junto con las horas UTC es, en esencia, la duplicación, y la conversión todavía está en la capa del modelo. Para solucionar esto, es posible que tenga una propiedad de tipo UTCToLocalTimeConverter de solo lectura en el usuario POCO que se inicializa con la zona horaria (lo que también elimina la necesidad de métodos estáticos). Entonces todas las llamadas a las propiedades de tiempo en las páginas se envolverán en el método ConvertToLocalTime del convertidor, que se puede acceder a través del usuario. También puede poner la instancia del convertidor directamente en Session, si lo desea.

No sé si este enfoque funcionaría para usted, pero está inspirado en su estrategia, y creo que el resto del diseño se ejecuta sin problemas pensando de esta manera. También la conversión a localtimes está aún a disposición del cliente. La desventaja es tener que convertir todos los valores de tiempo en el cliente, pero eso me parece un mal necesario a cambio de deshacerme de la duplicación de datos y los métodos estáticos.

+0

Supongo que ese es mi punto de vista, ¿debería saber mi capa de modelo en qué zona horaria está el usuario? Actualmente no. Mi debate interno es si esta es una presentación o una decisión de la capa modelo. Un usuario POCO almacena la zona horaria pero el usuario POCO no tiene atributos de tiempo que otros POCO hacen. Entonces estoy atando la visualización de los valores de un POCO a otro que no era necesario antes ... – toxaq

+0

He actualizado mi respuesta. – henginy

+0

Excelente, gracias. Veo lo que estás diciendo y para mí realmente es una sacudida entre dos "males necesarios". Como me gusta la simplicidad del consumo (y dado que actualmente soy el único que trabaja en ello), me mantendré en mi camino por el momento, pero creo que el suyo es igualmente válido y, desde luego, más transparente/legible. – toxaq

Cuestiones relacionadas