DDD中的应用级设置?

时间:2009-11-23 21:26:56

标签: domain-driven-design

只是想让小组了解如何处理实体的配置细节。

我正在考虑的是高级别设置,可能是管理员更改的。你可能最终存储在应用程序或web.config中的那种东西,但是从DDD角度来看应该明确地设置在对象的某个地方。

为了论证,我们以一个基于网络的CMS或博客应用为例。

给定博客条目实体具有任意数量的实例设置,如作者,内容等。

但您也可能想要设置(例如)默认描述或关键字,如果作者没有更改网站中的所有条目,则应该从这些条目开始。当然,你可以在课堂上制作这些常量,但网站所有者无法更改默认值。

所以我的想法如下:

1)使用类级别(静态)属性来表示这些设置,然后在应用程序启动时设置它们,从数据库或web.config设置它们。

2)使用单独的实体来保存设置,可能是字典,要么直接使用它,要么让它成为Entry类的成员

最容易/最灵活的是什么让你大家都感到震惊?我对第一个问题的关注是,它不会让我觉得非常可插拔(如果我最终想要添加更多功能),因为更改实体的类方法会让我改变应用程序本身(这感觉就像是OCP违规)。然而,第二个感觉它更重,特别是如果我必须从字典中强制转换或解析值。

1 个答案:

答案 0 :(得分:9)

我想说一个值是否可配置与域模型的观点无关 - 重要的是外部定义。

假设你有一个必须有名字的班级。如果始终需要Name,则必须将其封装为不变量,而不管值的来源如何。这是一个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的目标。

但是您询问了默认值。如果Name具有良好的默认值,那么如何将该默认值传递给MyClass。

这就是工厂派上用场的地方。您只需将对象的构造与其实现分开即可。无论如何,这通常是一个好主意。无论您选择抽象工厂还是构建器实现都不太重要,但抽象工厂是一个很好的默认选择。

对于MyClass,我们可以定义IMyClassFactory接口:

public interface IMyClassFactory
{
    MyClass Create();
}

现在,您可以定义从配置文件中提取名称的实现:

public ConfigurationBasedMyClassFactory : IMyClassFactory
{
    public MyClass Create()
    {
        var name = ConfigurationManager.AppSettings["MyName"];
        return new MyClass(name);
    }
}

确保需要MyClass实例的代码使用IMyClassFactory创建它而不是手动新建它。