There are objects, many named after the nouns in the domain space, and these objects are connected with the rich relationships and structure that true domain models have. The catch comes when you look at the behavior, and you realize that there is very little behavior on these objects. Indeed often these models come with design rules that say that you are not to put any domain logic in the the domain objects. Instead there are a set of service objects which capture all the domain logic. These services live on top of the domain model and use the domain model for data.
也就是说在领域模型中Q本w只处理很少的行为逻辑Q大多数都是处在模型上层的一pd的ServicecL负责捕获处理q些领域逻辑行ؓ(f)。这q背了OO思想QOO认ؓ(f)应该把数据和行ؓ(f)合在一P?/p>
Eric Evans在他的Domain Driven Design中说q:(x)
Application Layer [his name for Service Layer]: Defines the jobs the software is supposed to do and directs the expressive domain objects to work out problems. The tasks this layer is responsible for are meaningful to the business or necessary for interaction with the application layers of other systems. This layer is kept thin. It does not contain business rules or knowledge, but only coordinates tasks and delegates work to collaborations of domain objects in the next layer down. It does not have state reflecting the business situation, but it can have state that reflects the progress of a task for the user or the program.
Domain Layer (or Model Layer): Responsible for representing concepts of the business, information about the business situation, and business rules. State that reflects the business situation is controlled and used here, even though the technical details of storing it are delegated to the infrastructure. This layer is the heart of business software.
据说在Thoughtwork公司里面采用的技术是Hibernate+Spring+webworkQ关于anemia domain model有不员工在公司内部邮g中发问老马应该什么正用。但是老马q没有给出确切答案,只放入TODOList厅R?br /> 我个的DomailcM不应该含有过多的与之无关的行为,不但q反了单一职责的原则,q得整个系l不够稳定。例如User中有RolesQ那么addRole,removeRole自然应在DomaincUser中写Q至于removeUser,loadUser{应该封装成Daod理?/p>
引用robbin在一ơ讨Z的回复:(x)
我的理解是Martin大叔所谓的domain object?#8220;领域模型”Q它是一个针对业务逻辑抽象的模型,和Y件编E根本毫无关pR即使你不开发这个YӞ你仍焉要抽象你的业务逻辑得到你的领域模型。这个领域指的是你所从事的行业,而不是狭隘的持久化类?
q且领域模型的徏模也是在需求分析阶D,或者在需求分析阶D之前完成的事情。具体到~程的过E中Q领域模型ƈ非对应某一个Javac,如果一定要对应的话Q(业务对象QDao接口QHibernate实体c)他们合v来统U领域模型在Java语言的实现。把 商业建模范畴?#8220;领域模型”拿来当做Hibernate~程中的实体c,Ҏ(gu)是牛头不对马嘴!
其实你的d是把持久化实体cȝ持久化操作附着到实体类上面去,而不是分开。D例来_(d)也就是说Accountcȝ增删Ҏ(gu)不应该单独分dAccountDao接口去,而应该把增删Ҏ(gu)操作攑֜Accountc里面来完成Q对不?
那么我在解释q个问题之前Q必L清一点,是q个问题的讨论,x久化操作是否应该单独抽象一个DAO层的问题是和Martin Fowler提到了血的领域模型毫无关pȝ。实际上传统的Entity Bean是q种把持久化操作附着到Entity Bean本nȝQ但是Martin Fowler一样在_(d)q种Entity Bean是贫血的?
好了Q我们现在把其他无关因素排除了,focus到这个话题上Q就是我们是否需要DAO接口的问题了。因为按照你的观点,如果把对象的增删Ҏ(gu)都放在实体类上面Q其实我们就不需要DAO接口层了Q业务对象和W(xu)eb Action都可以直接调用实体类本n来完成持久化操作了?
大概?003q以前,我一直就是采用这U模型的Q但是从2003q开始,我就Ҏ(gu)了分M个DAO层来专门处理持久化操作了。原因是多方面的Q从技术角度来考量的话Q分d有很多好处,Rod Johnson在《without EJB》第10章持久化里面pl阐qC需要DAO层的理由Q我你看一下,q里不复qC。只谈一下除了Rod Johson提到理由之外的理由:(x)
作ؓ(f)保持状态的实体c,他的职责是保持状态,而不负责状态的持久化。如果把持久化操作也攑֜实体cMQ一斚w来说Q把两种不同的职责放在一个类中,q不W合OCP的单一职责的原则,然而更重要的原因是?x)带来实体类的不E_的问题?
在我的理念中Q实体类以及(qing)实体cd联关pL一个Y件系l中最E_不变的部分,在整个Y件系l中Q各个层面都需要涉?qing)到实体cȝ操作Q如何划分实体类Q以?qing)确定实体类兌是最费考量的,定了这一点,整个软gpȝ底层依赖关pd被确定下来了Q实体类的属性可以变化,׃软gpȝ对实体的操作都是以实体类为单位的Q所以实体属性的变化不会(x)造成pȝ不稳定)Q上面的DAO层,业务层,W(xu)eb层都只对实体cM生单向依赖?
如果你把DAO层合q到实体cMQ请注意本来Web层是不依赖于DAO层的QW(xu)eb层只依赖实体c(因ؓ(f)它要展现实体cȝ态)Q但是由于你合ƈ了,使得Web层也变得依赖那些DAO层的操作了。这L(fng)l果是让Y件系l的耦合性提高,可~性降低,可维护性降低?
DAO层的变动是大于实体类变动的,实体cd本上E_不变Q而Y件系l的需求变更几乎一定会(x)带来DAO层的变动Q但是ƈ不会(x)带来实体cd的变动(?x)带来实体属性的变动Q但是很会(x)影响到实体类本nQ。所以DAO层的变动频率q远大于实体cR那么当你把DAO层操作合q到实体cM后,其结果就是让实体cȝ变动频率{于DAO层的变动频率。那么就?x)造成本来E_的实体类层变得变得频率高了很多,而实体类的变动会(x)波及(qing)到Y件系l的每个层面Q造成软g大面U的相关性和不稳定?
误住很重要的一点:(x)实体cL有状态的c,DAOcL无状态的c,在整个Y件系l中Q只有两U类有状态,一个是实体c,一个是HTTP Session。有状态的cM(x)带来很高的代码相x,应该量减少有状态类的媄(jing)响范_(d)量减少有状态类的变动频率,应该量减少有状态类的职责?
而你把DAO操作合ƈ到实体类以后Q结果就是扩大了有状态类的代码相x的范围和媄(jing)响范_(d)扩大了有状态类的变动频率,最后就造成软gpȝ的稳定性下降?br />
public final class ArrayUtil {
private ArrayUtil(){
}
/**
* Code shared by RegressionLine and WeightedAverage to discard prefix-zeros of array.
* if all the elems of array are zero, return null.
*/
public static double[] discardPrefixZero(double[] data){
int firstNoZeroIndex = -1;
for(int i=0;i<data.length;i++) {
if(data[i] == 0d) {
continue;
}
else{
firstNoZeroIndex = i;
break;
}
}
if(firstNoZeroIndex == -1)
return null;
double[] data2 = new double[data.length-firstNoZeroIndex];
System.arraycopy(data, firstNoZeroIndex, data2, 0, data.length-firstNoZeroIndex);
return data2;
}