Где следует преобразовывать значения представления в многоуровневой архитектуре? - PullRequest
5 голосов
/ 22 октября 2010

Я создаю приложение, которое является многоязычным, многозонным и n-уровневым. Все даты хранятся в базе данных в формате UTC, а все объекты модели заполняются временем UTC. Однако время в формате UTC никогда не отображается (если только у пользователя не установлен часовой пояс UTC).

Это означает, что мне нужно периодически преобразовывать свойства времени в правильный часовой пояс пользователя. Повторение всегда является признаком плохого кода или лучшего способа, поэтому я пытался найти лучшую стратегию для реализации. Хотя это и есть логика представления, мои мысли изменились, потому что кажется, что модель должна знать правильные значения для текущего пользователя. Пока мои мысли таковы:

  1. Используйте статический вспомогательный класс, а затем вызывайте его каждый раз, когда используется свойство модели. Кажется, что это может привести к ошибкам или быть забытым, что делает вычисления громоздкими.

  2. Обернуть объект модели в объект модели представления. Это не менее громоздко, особенно при работе со списками объектов.

  3. Напишите метод расширения для модели, который существует только на уровне представления. Это кажется чище, но не интуитивно понятно.

  4. Создание интерфейса на уровне модели для преобразования. Реализуйте помощник на уровне представления и предоставьте реализации на уровне модели. Затем модель обладает свойствами, которые используют интерфейс для преобразования времени. Кажется, что это должно нарушить разделение интересов, но, похоже, это не так. Если бы у вас был конвертер по умолчанию, вам не пришлось бы беспокоиться о получении исключений нулевого объекта, однако тогда для слоя модели (в настоящее время POCO) понадобился бы контейнер для помощника преобразования, который выглядит грязным.

  5. Создать метод преобразования в местный часовой пояс для модели и передать текущий часовой пояс.

Меня интересуют мнения об этих или любых других стратегиях, которые я должен или мог бы использовать вместо них.

Обновление В настоящее время я создал ITimeConvertor и ITimeConvertorFactory на уровне модели. Затем я создал их реализации по умолчанию, которые просто возвращают исходное значение даты. В слой модели я добавил свойства локального времени для каждого существующего свойства UTC, которое было изначально в модели. В этих свойствах я использую фабрику, чтобы получить конвертер и конвертировать значение UTC в геттер и сеттер. Мне пришлось добавить класс статических настроек в слой модели (который мне не очень нравится) в качестве места для хранения текущей фабрики преобразователей времени. В части веб-приложения я реализую ITimeConvertorFactory и ITimeConvertor как WebTimeConvertorFactory и WebTimeConvertor. WebTimeConvertor знает о сеансе и текущем пользователе, поэтому может получить текущий часовой пояс. WebTimeConvertorFactory создает WebTimeConvertors. Когда приложение запускается (application_onstart в global.asax), я создаю фабрику и передаю ее в свойство статических настроек уровня модели. Это позволяет слою моей модели иметь возможность преобразовывать местное время, в то время как слой данных знает только о свойствах даты в формате UTC. Это также означает, что я могу передавать локальное время непосредственно в модель и точно преобразовывать его при условии, что приложение-потребитель предоставило фабрику преобразователей. Поскольку свойства UTC неизменны, они все равно могут использоваться в любом месте приложения. Хотя это казалось большим количеством кода, я нашел это решение достаточно чистым после его реализации, поскольку оно позволяет другим потребителям сервиса реализовывать преобразование своего времени так, как они хотят (если вообще хотят), в то же время сохраняя разумное потребление свойств модели. очевидно.

Я все еще открыт для лучших решений и критики моего текущего решения.

1 Ответ

2 голосов
/ 24 октября 2010

Я предполагаю, что именно ваш модельный слой знает о часовом поясе пользователя, поэтому преобразование временных свойств зависит от уровня модели. В противном случае вам нужно будет сообщить на уровне представления о часовом поясе и преобразовать каждое значение времени там.

Преобразование значений времени на уровне модели позволило бы использовать их на уровне представления без каких-либо преобразований, поэтому я думаю, что это будет чисто. Например, вы можете инициализировать ваши объекты (POCO) с преобразованным временем в начале. Но остерегайтесь повторного преобразования их в модель, забывая, что они уже инициализированы по местному времени. Кроме того, если пользователь может редактировать значения времени, вам потребуется преобразовать их обратно в время UTC перед сохранением.

Обновление: Подумав еще немного, я понял, что время UTC является частью модели, а местное время является представлением этой модели, поэтому обязанность преобразования больше относится к уровню представления (за счет несогласия с собой). При одном и том же мыслительном процессе наличие свойств локального времени вместе с временем UTC по сути является дублированием, и преобразование все еще находится на уровне модели. Чтобы преодолеть это, у вас может быть свойство readonly UTCToLocalTimeConverter -type в пользовательском POCO, которое инициализируется с часовым поясом (что также устраняет необходимость в статических методах). Тогда все вызовы временных свойств на страницах будут обернуты в метод ConvertToLocalTime конвертера, который доступен через пользователя. Вы также можете поместить экземпляр конвертера непосредственно в Session, если хотите.

Я не знаю, сработает ли этот подход для вас, но он вдохновлен вашей стратегией, и я думаю, что остальная часть дизайна работает более плавно, думая таким образом. Также преобразование в местное время все еще в распоряжении клиента. Недостатком является необходимость преобразования всех значений времени в клиенте, но это кажется мне необходимым злом в обмен на избавление от дублирования данных и статических методов.

...