design-patterns - 在多层架构中应该在哪里进行表示值的转换?

标签 design-patterns architecture timezone

我正在构建一个多语言、多时区和 n 层的应用程序。所有日期都以 UTC 格式存储在数据库中,所有模型对象都使用 UTC 时间填充。然而 UTC 时间永远不会显示(除非用户碰巧将他们的时区设置为 UTC)。

这意味着我需要重复地将时间属性转换为正确的用户时区。重复总是错误代码或更好方法的标志,因此我试图制定最佳实现策略。尽管这实际上是表示逻辑,但我的想法已经发生了变化,因为似乎模型应该知道当前用户的正确值。到目前为止,我的想法是:

  • 使用静态帮助类,然后在每次使用模型的属性时调用它。这似乎容易出错或被遗忘,并且使计算变得繁琐。
  • 将模型对象包装在 viewmodel 对象中。这同样很麻烦,尤其是在处理对象列表时。
  • 为仅存在于表示层的模型编写扩展方法。这看起来更干净但不直观。
  • 在模型层中为转换创建一个接口(interface)。在表示层实现助手并给模型层实现。然后模型具有使用接口(interface)转换时间的属性。这似乎应该打破关注点分离,但似乎没有。如果您有一个默认转换器,那么您不必担心会出现空对象异常,但是模型层(当前为 POCO)将需要一个用于转换助手的容器,这看起来很困惑。
  • 在模型上创建一个转换为本地时区的方法并传入当前时区。

  • 我对这些策略的意见或我应该或可以用来代替这些策略的任何其他意见感兴趣。

    更新
    我目前所做的是在模型层中创建一个 ITimeConvertor 和一个 ITimeConvertorFactory 。然后我创建了这些的默认实现,它们只返回原始日期值。在模型层中,我为模型中最初存在的每个现有 UTC 属性添加了本地时间属性。在这些属性中,我使用工厂获取转换器并在 getter 和 setter 中以每种方式转换 UTC 值。我不得不在模型层(我不太喜欢)中添加一个静态设置类作为存储当前时间转换器工厂的地方。在 Web 应用程序部分中,我将 ITimeConvertorFactory 和 ITimeConvertor 实现为 WebTimeConvertorFactory 和 WebTimeConvertor。 WebTimeConvertor 知道 session 和当前用户,因此可以获取当前时区。 WebTimeConvertorFactory 创建 WebTimeConvertor。当应用程序启动时(global.asax 中的 application_onstart),我创建工厂并将其传递给模型层静态设置属性。这使我的模型层能够转换本地时间,而数据层只知道 UTC 日期属性。这也意味着我可以将本地时间直接传递到模型中,并在消费应用程序提供转换器工厂的情况下对其进行准确转换。由于 UTC 属性没有改变,它们仍然可以在应用程序内的任何地方使用。
    虽然它看起来像很多代码,但我发现这个解决方案在实现后非常干净,因为它允许服务的其他消费者以他们想要的任何方式(如果有的话)实现他们的时间转换,同时还可以合理地保持模型属性的消耗明显的。

    我仍然对更好的解决方案和对我当前解决方案的批评持开放态度。

    最佳答案

    我假设是您的模型层知道用户的时区,因此由模型层来转换时间属性。否则,您将不得不让表示层知道时区,并在那里转换每个时间值。

    在模型层转换时间值可以在表示层中使用它们而无需任何转换,所以我认为这很干净。例如,您可以在开始时使用转换时间初始化您的对象 (POCO)。但要注意不要在模型中重新转换它们,忘记它们已经初始化为本地时间。此外,如果用户可以编辑时间值,则需要在保存之前将它们转换回 UTC 时间。

    更新:
    经过一番思考,我认为 UTC 时间是模型的一部分,而 localtimes 是该模型的 View ,因此转换职责更多地属于表示层(以不同意我自己为代价)。同样的思路,localtime属性和UTC时间本质上是重复的,转换还是在模型层。为了克服这个问题,你可能有一个只读的 UTCToLocalTimeConverter用户 POCO 中的 -type 属性,它使用时区初始化(这也消除了对静态方法的需要)。然后所有对页面中时间属性的调用都将包含在转换器的 ConvertToLocalTime 中。方法,可通过用户访问。您可以将转换器实例直接放入 Session如果你愿意,也可以。

    我不知道这种方法是否适合你,但它受到了你的策略的启发,我认为其余的设计以这种方式运行起来会更顺畅。此外,转换为本地时间仍由客户支配。缺点是必须转换客户端中的所有时间值,但在我看来,这似乎是一种必要的邪恶,以换取摆脱数据重复和静态方法。

    关于design-patterns - 在多层架构中应该在哪里进行表示值的转换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3993172/

    相关文章:

    javascript - Backbone.js:.render() 和 .remove() 应该能够相互逆转吗?

    java - UTC Unix 时间戳存储在错误时区的 Java 程序中的 HSQLDB 中

    timezone - 在 Luxon 中设置时间并以用户的本地时区显示

    design-patterns - 您如何在设计和(实际)实现应用程序之间取得平衡

    java - Android 应用程序中的 MVP 与事件驱动

    php - 包含另一个 php 文件时如何构造 javascript

    python - pytz 本地化与日期时间替换

    c++ - 尝试实现访问者设计模式时出现编译器错误

    Javascript:模块模式与构造函数/原型(prototype)模式?

    architecture - 使用缓存或应用程序范围创建命中计数器