Domain driven design DDD中的应用程序级别设置?

Domain driven design DDD中的应用程序级别设置?,domain-driven-design,Domain Driven Design,只是想让小组思考如何处理实体的配置细节 我特别想到的是可能会被管理员更改的高级设置。最终,您可能会存储在app或web.config中,但从DDD的角度来看,应该在对象中的某个位置显式设置 为了便于讨论,让我们以基于web的CMS或博客应用程序为例 给定的博客条目实体具有任意数量的实例设置,如作者、内容等 但您也可能希望设置(例如)默认描述或关键字,如果作者没有更改,则站点中的所有条目都应以这些描述或关键字开头。当然,您可以在类中创建这些常量,但是站点所有者无法更改默认值 因此,我的想法如下:

只是想让小组思考如何处理实体的配置细节

我特别想到的是可能会被管理员更改的高级设置。最终,您可能会存储在app或web.config中,但从DDD的角度来看,应该在对象中的某个位置显式设置

为了便于讨论,让我们以基于web的CMS或博客应用程序为例

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

但您也可能希望设置(例如)默认描述或关键字,如果作者没有更改,则站点中的所有条目都应以这些描述或关键字开头。当然,您可以在类中创建这些常量,但是站点所有者无法更改默认值

因此,我的想法如下:

1) 使用类级别(静态)属性来表示这些设置,然后在应用程序启动时进行设置,可以从DB或web.config进行设置

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


你们觉得什么最容易/最灵活?我对第一个问题的担忧是,它对我来说不是非常可插拔(如果我最终想要添加更多功能),因为更改实体的类方法也会使我更改应用程序本身(这感觉像是违反OCP)。但是,第二个问题感觉更为沉重,特别是如果我必须从字典中转换或解析值。

我想说,从域模型的角度看,值是否可配置是无关紧要的,重要的是它是外部定义的

假设您有一个必须有名称的类。如果名称始终是必需的,则必须将其封装为不变量,而不考虑值的来源。下面是一个C#示例:

这样的类有效地保护了不变量:Name不能为null。领域模型必须像这样封装不变量,而不考虑哪个消费者将使用它们——否则,它们将无法满足灵活设计的目标

但您询问了默认值。如果名称有一个好的默认值,那么如何将该默认值传递给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来创建它,而不是手动新建它。

默认值就是一个例子,可能是一个糟糕的例子;我熟悉工厂的模式。另一个例子是应该应用于类的所有实例,但可以在应用程序级别更改。可能类似于要加载到列表中的实例数(始终)或关于是否显示注释的规则。这些值对我来说并不是实例级的值,或者我误解了什么?您可以将一个或多个相关值封装到一个类型中,然后将该类型的实例注入到所有使用者中。出于效率原因(或任何其他原因),您可以选择注入单个共享实例,而使用者不知道注入对象的生存期。这将使您的选项保持打开状态。@MarkSeemann如果我想在我的富域模型中有可配置的逻辑,该怎么办?例如,像一个简单的
bool
设置来确定计算方法。我应该把这个布尔值也传给构造函数吗?@Konrad。正如所解释的,布尔标志很少表示良好的设计。通常情况下,多态性可能更可取,但归根结底,软件设计是要权衡多个关注点,因此如果没有对特定上下文的广泛了解,就不可能有明确的答案。@MarkSeemann不管它是布尔值还是其他值,但我们可以说,这是一种决定价格计算方式的设置。我想一定有一些一般性的答案。
public ConfigurationBasedMyClassFactory : IMyClassFactory
{
    public MyClass Create()
    {
        var name = ConfigurationManager.AppSettings["MyName"];
        return new MyClass(name);
    }
}