Настройки уровня приложения в DDD?
Просто хотелось, чтобы группы подумали, как обрабатывать детали конфигурации сущностей.
Что я имею в виду, в частности, настройки высокого уровня, которые могут быть изменены администратором. В конечном итоге вы можете хранить такие вещи в приложении или web.config, но с точки зрения DDD их следует явно указывать где-то в объектах.
Для примера давайте возьмем в качестве примера веб-приложение CMS или блог.
У данного объекта "Запись в блоге" есть любое количество настроек экземпляра, таких как "Автор", "Контент" и т. Д.
Но вы также можете установить (например) описание по умолчанию или ключевые слова, с которых должны начинаться все записи на сайте, если они не были изменены автором. Конечно, вы можете просто сделать эти константы в классе, но тогда владелец сайта не сможет изменить значения по умолчанию.
Поэтому мои мысли таковы:
1) использовать (статические) свойства класса для представления этих настроек, а затем устанавливать их при запуске приложения, устанавливая их из БД или из файла web.config.
или же
2) использовать отдельный объект для хранения настроек, возможно, словарь, либо использовать его напрямую, либо он должен быть членом класса Entry
Что кажется вам наиболее легким / гибким? Что касается меня, то, во-первых, меня беспокоит то, что это не кажется мне очень подключаемым (если я в итоге захочу добавить больше функций), так как изменение методов класса объекта заставит меня изменить и само приложение (что похоже на нарушение OCP).). Второй кажется, что он более тяжелый, особенно если мне тогда придется приводить или анализировать значения из словаря.
1 ответ
Я бы сказал, что то, является ли значение настраиваемым или нет, не имеет значения с точки зрения модели предметной области - важно то, что это определяется внешне.
Допустим, у вас есть класс, который должен иметь имя. Если имя всегда требуется, оно должно быть инкапсулировано независимо от источника значения. Вот пример C#:
public class MyClass
{
private string name;
public MyClass(string name)
{
if(name == null)
{
throw new ArgumentNullException("name");
}
this.name = name;
}
public string Name
{
get { return this.name; }
set
{
if(value == null)
{
throw new ArgumentNullException("name");
}
this.name = value;
}
}
}
Такой класс эффективно защищает инвариант: имя не должно быть нулевым. Доменные модели должны инкапсулировать подобные инварианты безотносительно к тому, какой потребитель будет их использовать, иначе они не будут соответствовать цели Supple Design.
Но вы спросили о значениях по умолчанию. Если у вас есть хорошее значение по умолчанию для имени, то как передать это значение по умолчанию в MyClass.
Здесь фабрики пригодятся. Вы просто отделяете конструкцию своих объектов от их реализации. Это часто хорошая идея в любом случае. Независимо от того, выберете ли вы Abstract Factory или Builder, реализация менее важна, но Abstract Factory - хороший выбор по умолчанию.
В случае MyClass мы могли бы определить интерфейс IMyClassFactory:
public interface IMyClassFactory
{
MyClass Create();
}
Теперь вы можете определить реализацию, которая извлекает имя из файла конфигурации:
public ConfigurationBasedMyClassFactory : IMyClassFactory
{
public MyClass Create()
{
var name = ConfigurationManager.AppSettings["MyName"];
return new MyClass(name);
}
}
Убедитесь, что код, которому нужны экземпляры MyClass, использует IMyClassFactory для его создания вместо того, чтобы создавать его вручную.