一起聊一下DDD里显式的约束的理解

DDD第166页,关于显式的约束有这样的话:
下面是一些警告信号,表明约束正在误导它所属的对象设计
×从对象的定义发现,判断约束所需的数据本来不应该属于这个对象;
×相关规则在多个对象中出现,造成代码的重复,或者使对象之间出现了本来不应出现的继承关系;
×有许多设计和需求讨论都是围绕约束展开的,但是这些规则在实现上却被隐藏到了过程性的代码中。
如果约束使对象的基本职责变得模糊,或者约束在领域中非常显眼而在模型中却若隐若现,那么您就可以将它分解出来,使之成为一个显式的对象,甚至将它建模为一系列对象的关系。

业务规则往往不适于放在任何一个实体或值对象中,而且规则的变化和组合会掩盖那些领域对象的基本含义。但是,将这些规则移出领域层会更加糟糕,因为领域代码不再能够表达模型了。
逻辑程序设计为我们提供了一种概念,即利用“谓”词来分离和组合规则对象。不过,要把这种概念完全用对象实现出来还是比较困难。而且这种概念也过于通用,在交流意图的时候它还不如一个更有针对性的设计。

思考:
如果想做一个行业的产品,考虑到很多未知的规则和可配置的规则,我是否要对所有的规则约束都创建一个类呢?


大家可以谈谈对这点的理解吗?
[该贴被windflaw于2007年04月23日 21:10修改过]
[该贴被windflaw于2007年04月23日 21:14修改过]

>考虑到很多未知的规则和可配置的规则,我是否要对所有的规则约束都创建一个类呢?

原则上是这样,如果觉得类个数太多,这里面可以根据规则共性进行合并,或使用设计模式进行重构.

>这里面可以根据规则共性进行合并,或使用设计模式进行重构.

可以举个例子吗?比如果说有个业务:要登记员工某个月的奖惩情部。有这样的规则:1、如果员工非在职,不可以添加奖惩;2、如果这个月的工资已经算完了,不可以添加奖惩;3、一个月内多次奖利的总金额不可以超过1000。——仅是例子,不必考虑真实性。

是不是按DDD里的方式,3个规则就可以写三个类?如果这样,规则类在系统里不知道要多少,如果进行合并,如果进行重构,是否可以指点一二

具体问题具体研究.

就你这个案例,还是有共性的,就是属于奖惩类.

可以将多个规则封装在一起,总是会有同类的.

这其实又回到对象创建中,Evans DDD告诉我们如何根据业务情况创建类,但是没有告诉我们是否可主观人为创建类,回答是可以的,这个问题已经在GoF设计模式中得到解答,象Facade等类都是和具体业务无关,只是用来实现管理,分类的类.

那是否可以写成:


public class Reward{...}

public class RewardRule
{
public bool IsSatisfy(Reward reward)
{
// 判断员工是否在职
// 本月工资是否算完
// 判断本月奖利总金额是否会超过1000
}
}

public class RewardService
{
public void AddReward(Reward newReward)
{
RewardRule rule = new RewardRule();
if(rule.IsSatisfy(newReward))
{
// 将new Reward添加到Reward仓储
}
}
}


[该贴被windflaw于2007年04月26日 15:44修改过]

如果更复杂一点,作为产品,会提供一些参数配置,那么是否可以这样:

软件产品将由实施人员根据实情对业务规则参数进行设置,有以于三个参数:

1、是否可以对非在职员工进行奖利 [Yes|No]
2、在本月工资结算完毕是否可以对当月再维护奖利 [Yes|No]
3、每个月最高奖利限制金额:______(不填将,或填0代表不作任何限制)

代码:


public class RewardConfig
{
public bool OnlyOnTheJob; // 是否可以对非在职员工进行奖利
public bool IsLockAfterSalaryCalculated; // 在本月工资结算完毕是否可以对当月再维护奖利
public decimal LimitAmount; // 每个月最高奖利限制金额
}

public class RewardRule
{
private bool m_onlyOnTheJob;
private bool m_lockAfterCaluclated;
private decimal m_limitAmount;

public RewardRule(bool onlyOnTheJob, bool lockAfterCalculated, decimal limitAmount)
{
m_onlyOnTheJob = onlyOnTheJob;
m_lockAfterCaluclated = lockAfterCalculated;
m_limitAmount = limitAmount;
}
public bool IsSatisfy(Reward reward, RewardConfig config)
{
if(m_onlyOnTheJob)
{
if(!IsOnTheJob(reward))
return false;
}
if(m_lockAfterCaluclated)
{
if(!IsSalaryCalculated(reward))
return false;
}
if(m_limitAmount>0)
{
if(!IsInLimitAmount(reward))
return false;
}
return true;
}
private bool IsOnTheJob(Reward r)
{
// 判断员工是否在职
}
private bool IsSalaryCalculated(Reward r)
{
// 本月工资是否算完(需求操作到数据库)
}
private bool IsInLimitAmount(Reward r)
{
// 判断本月奖利总金额是否会超过1000(需求操作到数据库)
}
}

public class RewardService
{
private RewardConfig m_config;

public void Add(Reward newReward)
{
RewardConfig config = this.GetConfig();
RewardRule rule = new RewardRule(config.OnlyOnTheJob, config.IsLockAfterSalaryCalculated, config.LimitAmount);
rule.IsSatisfy(newReward);
RewardRepository.Add(newReward);
}
public RewardConfig GetConfig()
{
if(m_config == null)
{
// 读取config数据
}
return m_config;
}
}
public class RewardRepository
{
public static void Add(Reward reward)
{
// 插入数据库
}
}