Frage

EDIT:

Weil ich mit der Vergabe die ursprüngliche Prämie von 300 zu spät war, um zu @arcain ich wieder zu öffnen. Und die zusätzliche 150 Vergabe an @arcain. Es sei denn natürlich jemand bietet auch eine bessere Antwort. :)

/ EDIT

Betrachten Sie die folgende Form:

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]

Die Einstellungen der obigen Tabelle werden in einer DB-Tabelle gespeichert werden, die Spalten zu den oben genannten Spalten Karte (mit Ausnahme der letzten Spalte offensichtlich).

Alle (Speichern und Löschen) Aktionen auf eine Lokalisierung Controller lenken. Die Lokalisierung Controller im Grunde rufen Methoden auf einem LocalizationService, etwa so:

$localizationService->updateCollection( $_POST ) // update collection settings
// or
$localizationService->delete( $_POST ) // delete a single locale

Die LocalizationService in seiner wiederum ruft eine LocaleMapperDb, so etwas wie folgt aus:

foreach( $localeCollection as $locale )
{
    $localeMapperDb->update( LocaleModel $locale );
}
// or
$localeMapperDb->delete( LocaleModel $locale );

Wo aber ist die Verantwortung für das Speichern Sie diese Einstellung:

[x] let visitors browser-settings determine default language

Es wird in einer DB-Tabelle gespeichert wird site_settings genannt. Ich habe gedacht, ein paar Optionen:

  • Verwenden Sie einen Site / SiteSettingsService im LocalizationController. Aber dann wird die komplette Form erzeugt und bereits in der LocalizationService verarbeitet werden.
  • Verwenden Sie ein SiteMapperDb / SiteSettingsMapperDb im LocalizationService und verwenden Sie es in updateCollection ($ _POST)
  • Verwenden Sie ein SiteMapperDb / SiteSettingsMapperDb im LocaleMapperDb

Die ersten und letzten Optionen aussehen wie die schlimmsten Optionen, aber ich bin nicht sicher. Was fühlen Sie, ist die beste Option? Oder vielleicht haben Sie eine Alternative, habe ich nicht gedacht?

War es hilfreich?

Lösung

I think projecting domain model objects onto view model objects works well in this situation.

In the case of the attached code (please pardon me for writing it in C#; it should be fairly portable) the domain model objects are never exposed (they only are accessed directly within the service objects.) The services only expose view model objects, like LocalViewModel, and those view model objects are manipulated by the controllers.

The LocaleConfigController also maps the data returned by the services into a LocaleConfigViewModel object, and this object is the only object that is exchanged directly with the view.

So, in a nutshell, the view has a dedicated controller, and the view communicates with the controller via the LocaleConfigViewModel object. The controller manipulates the LocaleConfigViewModel object and calls into implementations of the ILocaleConfigService and the ISystemConfigService. The service objects never expose the domain model to the controller, and they are responsible for mapping view model objects to domain model objects (via whatever persistence mechanism is desirable.)

Note that the locale service is a configuration service, it would not have any implementation to look up what the correct localized strings would be. I would put that into another service, because it could be used in places where you would not want to expose any methods that would allow the alteration of the localization config.

For example, in the management side of the application, you would want both the localization config service and localization string rendering service (since the management site could be localized as well.) For a customer facing front end, you would instead probably want only the localization string rendering service, because system configuration modifications should be unwanted and out of scope for that site.

So, to finally answer your question: the controller contains references to both the locale and system configuration services, and the controller is dedicated to the view -- it has a well-defined contract where only LocaleConfigViewModels are exchanged.

As for where the responsibility lies for saving the system-wide settings, the controller is responsible for unpacking the system settings from the LocaleConfigViewModel and pushing them into the appropriate services (in this case the ISystemConfigService instance) where they will be persisted.

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; }
  // ...
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top