确定保存设置(控制器,服务和映射器)的责任
题
编辑:
因为我很晚才授予最初的赏金 300
要@arcain我重新开放。并授予其他 150
到@arcain。除非有人提供更好的答案。 :)
/ 编辑
考虑以下表格:
language | region | active | default |
-----------------------------------------------
en | GB | [x] | (*) | [X delete]
nl | NL | [x] | ( ) | [X delete]
nl | BE | [x] | ( ) | [X delete]
[x] let visitors browser-settings determine the default language
[save]
上表的设置将保存在DB表中,该表将列映射到上面的列(显然不包括最后一列)。
所有(保存和删除)操作直接直接归于本地化控制器。本地化控制器基本上调用了interizationservice上的方法,例如:
$localizationService->updateCollection( $_POST ) // update collection settings
// or
$localizationService->delete( $_POST ) // delete a single locale
依次称为localemapperdb,诸如此类:
foreach( $localeCollection as $locale )
{
$localeMapperDb->update( LocaleModel $locale );
}
// or
$localeMapperDb->delete( LocaleModel $locale );
但是,保存此设置的责任是:
[x] let visitors browser-settings determine default language
它将保存在名为site_settings的DB表中。我想到了一些选择:
- 在本地化controller中使用SiteSerservice / SiteSettingsService。但是随后,完整的表格已经在本地化服务中生成和处理。
- 在本地化服务中使用siteMapperDB / stiteSettingsMapperDB,并在UpdateCollection($ _POST)中使用它
- 在localemapperdb中使用siteMapperDB / stiteSettingsMapperDB
第一个也是最后一个选项看起来像是最糟糕的选择,但我不确定。您觉得最好的选择是什么?或者,也许您有其他选择,我没有想到?
解决方案
我认为将域模型对象投影到视图模型对象在这种情况下效果很好。
对于附件代码(请原谅我在C#中写下它;应该是相当便携的),域模型对象永远不会公开(它们仅在服务对象中直接访问。)服务仅公开视图模型对象,喜欢 LocalViewModel
, ,这些视图模型对象由控制器操纵。
这 LocaleConfigController
还将服务返回的数据映射到 LocaleConfigViewModel
对象,此对象是直接与视图交换的唯一对象。
因此,简而言之,该视图具有专用控制器,并且该视图通过 LocaleConfigViewModel
目的。控制器操纵 LocaleConfigViewModel
对象并调用实施 ILocaleConfigService
和 ISystemConfigService
. 。服务对象永远不会将域模型暴露于控制器,并且负责将视图模型对象映射到域模型对象(通过任何持久性机制是可取的。)
请注意,语言环境服务是 配置 服务,它将没有任何实施来查找正确的本地化字符串。我会将其放入另一个服务中,因为它可以在您不想揭示允许更改本地化配置的任何方法的地方使用。
例如,在应用程序的管理端,您需要本地化配置服务和本地化字符串渲染服务(由于管理站点也可以进行本地化。)对于面向前端的客户,您可能只需要本地化字符串渲染服务,因为系统配置修改应该是不需要的,并且该站点的范围不超出范围。
因此,最终回答您的问题:控制器包含对语言环境和系统配置服务的引用,并且控制器专用于视图 - 它具有明确的合同,仅在其中 LocaleConfigViewModel
S交换。
至于保存系统范围内设置的责任的位置,控制器负责解开系统设置 LocaleConfigViewModel
并将它们推入适当的服务(在这种情况下 ISystemConfigService
实例)将在其中坚持下去。
class LocaleViewModel
{
public int Id;
public string Language;
public string Region;
public bool Enabled;
public bool Deleted;
}
class LocaleConfigViewModel
{
public bool UseVisitorBrowserLocale;
public LocaleViewModel DefaultLocale;
public List<LocaleViewModel> Locales;
}
class LocaleConfigController : ILocaleConfigController
{
ILocaleConfigService localeConfig;
ISystemConfigService systemConfig;
public void Save(LocaleConfigViewModel model)
{
foreach (var locale in model.Locales)
{
if (locale.Deleted)
{
localeConfig.DeleteLocale(locale);
continue;
}
localeConfig.UpdateLocale(locale);
}
systemConfig.DefaultLocaleId = model.DefaultLocale.Id;
systemConfig.UseVisitorBrowserLocale = model.UseVisitorBrowserLocale;
}
public LocaleConfigViewModel GetCurrentView()
{
var model = new LocaleConfigViewModel();
model.Locales = localeConfig.Locales;
model.DefaultLocale = model.Locales.FirstOrDefault(l => l.Id == systemConfig.DefaultLocaleId);
model.UseVisitorBrowserLocale = systemConfig.UseVisitorBrowserLocale;
return model;
}
// ...
}
interface ILocaleConfigController
{
void Save(LocaleConfigViewModel model);
LocaleConfigViewModel GetCurrentView();
// ...
}
interface ILocaleConfigService // services will be stateless and threadsafe
{
void DeleteLocale(LocaleViewModel locale);
void UpdateLocale(LocaleViewModel locale);
List<LocaleViewModel> Locales { get; }
// ...
}
interface ISystemConfigService // services will be stateless and threadsafe
{
int DefaultLocaleId { get; set; }
bool UseVisitorBrowserLocale { get; set; }
// ...
}