java 领域模型模式示例
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/41335249/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Domain Model pattern example
提问by Aleksander Monk
I'm just trying to find some examples of Martin Fowler's Domain Modelpattern and I can't.
我只是想找到一些 Martin Fowler 的领域模型模式的例子,但我不能。
From what I found on the Internet Domain Model is just adding some "logic" methods to classes. For example
从我在 Internet 域模型上发现的内容来看,只是向类添加了一些“逻辑”方法。例如
public class Income {
private String title;
private String comment;
private String date;
private Double amount;
private Integer category;
public ExIn(String title, String comment, Double amount, Integer category, String date) {
this.title = title;
this.comment = comment;
this.date = date;
this.amount = amount;
this.category = category;
}
public Integer getCategory() {
return category;
}
public void setCategory(Integer category) {
this.category = category;
}
// more getters and setters
// Domain Model part starts
public boolean isPositive()
{
return amount > 0 ? true : false;
}
// more methods like that
}
Did I understand it correctly? If not, I'd be grateful for a little example of Domain Model Pattern usage.
我理解正确吗?如果没有,我会很感激域模型模式使用的一个小例子。
回答by davidxxx
Did I understand it correctly? If not, I'd be grateful for a little example.
我理解正确吗?如果没有,我会很感激一个小例子。
Broadly, yes.
大体上,是的。
From Martin Fowler, domain model is an object model of the domain that incorporates both behavior and data.
The domain model is frequently opposed to a model where you have specific classes to bear data and some other specific classes to bear behavior/processings.
从马丁福勒,领域模型是既包含行为和数据域的一个对象模型。
领域模型经常与模型相反,在这种模型中,您有特定的类来承载数据,而其他一些特定的类来承载行为/处理。
If I take your Income
class, it looks like more as a class that holds properties/data than an domain model with a real behavior.
如果我上你的Income
课,它看起来更像是一个保存属性/数据的类,而不是具有真实行为的域模型。
public boolean isPositive(){
return amount > 0 ? true : false;
}
is a kind of utility function that has no relation with the model.
You could put that in a Math
class.
是一种与模型无关的效用函数。
你可以把它放在一个Math
类中。
I will try to give you a domain model example and then the version where the model separates data and processing.
我将尝试为您提供一个域模型示例,然后是模型将数据和处理分开的版本。
Suppose in the requirements of the domain of the application you are modeling, we need to add a bonus for incomes. This bonus may take place in winter for Christmas for example (but why not for other events)
假设在您建模的应用程序域的要求中,我们需要为收入添加奖金。例如,这个奖金可能会在冬天的圣诞节发生(但为什么不用于其他活动)
Rather than having a service class to do this processing, we let domain model objects perform the task.
我们让域模型对象执行任务,而不是让服务类来执行此处理。
Incomes
, a high level object could iterate on Income
instances and apply the bonus and we could have a bonus rule class that defines the bonus according to some input values.
I introduce multiple classes since the idea is to allow each objects to collaborate according to their responsibilities.
Incomes
,一个高级对象可以迭代Income
实例并应用奖励,我们可以有一个奖励规则类,根据一些输入值定义奖励。
我引入了多个类,因为这个想法是让每个对象根据它们的职责进行协作。
Incomes :
收入:
public class Incomes {
List<Income> incomes = ...
....
public void applyBonus(BonusRule bonusRule){
for (Income income : incomes){
income.applyBonus(bonusRule);
}
}
Income :
收入 :
public class Income {
private float amount;
...
public void applyBonus(BonusRule bonusRule){
float bonus = bonusRule.compute(this);
amount += bonus;
}
...
}
ChristmasRule :
圣诞节规则:
public class ChristmasBonusRule implements BonusRule {
...
@Override
public float compute(Income income){
float bonus = ...
return bonus;
}
...
}
And finally, we could apply the processing in this way :
最后,我们可以以这种方式应用处理:
void foo(){
// create a domain object that has both behavior and data
Incomes incomes = ...;
// invoke a functional method on the object by passing another domain object
incomes.applyBonus(new ChristmasBonusRule());
}
In a design where you separate data and logic in distinct classes, it could look like more like that :
在将数据和逻辑分离到不同类中的设计中,它可能看起来更像这样:
public class IncomeBonusService {
// stateless : no incomes data inside it
....
public void applyChristmasBonus(List<Income> incomes){
for (Income income : incomes){
// Christmas bonus computation here
float bonus = ...
income.setAmount(bonus + income.getAmount());
}
}
}
And we could apply the processing in this way :
我们可以以这种方式应用处理:
// inject the service
@Autowired
IncomeBonusService incomeBonusService;
void foo(){
// create a domain object that has only data
List<Income> incomes = ...;
// invoke a service method by passing data as parameter
incomeBonusService.applyChristmasBonus(incomes);
}
A model design where the objects have no behavior (only getter/setter) is called Anemic Domain Model.
对象没有行为(只有 getter/setter)的模型设计称为贫血域模型。
Big differences between the two ways illustrated by this example :
此示例说明的两种方式之间的巨大差异:
Domain model :
领域模型:
The objects are meaningful.
Behavioral responsibility finely defined between classes.
So good isolation, testability and maintainability.
For example, adding/removing/unit-testing aBonusRule
is easy.Objects responsible of their state.
Indeed, no need to provide setters as the object can itself update its state after collaborating with other objects.
We could see that inAmount.applyBonus()
:float bonus = bonusRule.compute(this); amount += bonus;
对象是有意义的。
在类之间精细定义了行为责任。
因此具有良好的隔离性、可测试性和可维护性。
例如,添加/删除/单元测试 aBonusRule
很容易。负责其状态的对象。
实际上,不需要提供设置器,因为对象可以在与其他对象协作后自行更新其状态。
我们可以看到Amount.applyBonus()
:float bonus = bonusRule.compute(this); amount += bonus;
Anemic Domain Model :
贫血领域模型:
All the logic is in the service class.
So a single place to get the code.
With few lines, it is fine.
But note that this advantage has a certain limit because as the logic becomes big or complex, the best thing is often splitting the logic in multiple service classes.But whatever the number of Service classes you need, the whole logic is located in the service classes and not somewhere else. Which may ease development norms if we compare it to the domain model where the logic may be exploded in some different "types" of classes.
Necessity to provide getter/setter for domain classes.
The domain is not responsible of its state and its invariant rules either.
So any class that depends on the domain class can "break" its state.
所有的逻辑都在服务类中。
所以一个地方来获取代码。
用几行,没问题。
但请注意,这种优势有一定的局限性,因为随着逻辑变大或变复杂,最好的做法通常是将逻辑拆分为多个服务类。但是无论您需要多少服务类,整个逻辑都位于服务类中,而不是其他地方。如果我们将其与逻辑可能在某些不同“类型”的类中分解的域模型进行比较,这可能会简化开发规范。
需要为域类提供 getter/setter。
域也不对其状态和不变规则负责。
所以任何依赖于域类的类都可以“破坏”它的状态。
As a side note, some frameworks (for persistence, mapping, serialization, ...) rely by default on getter/setter.
That's why this model, despite its drawbacks, leads in some projects.
作为旁注,一些框架(用于持久性、映射、序列化等)默认依赖于 getter/setter。
这就是为什么这个模型尽管有缺点,但在一些项目中领先。
回答by Fuhrmanator
Fowler's book that you cite refers to Larman's bookfor introductory understanding and examples.
您引用的 Fowler 的书是指Larman 的书,用于介绍性理解和示例。
Interestingly, Larman's approach to domain modeling doesn't ever add behavior to domain classes.
有趣的是,Larman 的域建模方法从未向域类添加行为。
There is a notion in a domain model that a class is conceptualand is not a software class, but that software classes are based on domain (conceptual) classes. Larman's approach to implementing behavior follows responsibility driven design, and GoF design patterns.
领域模型中有一个概念,即类是概念性的,而不是软件类,但软件类是基于领域(概念)类的。Larman 实现行为的方法遵循责任驱动设计和 GoF 设计模式。
The domain model remains a separate element in the software development process. The good aspect of this way of modeling is you separate the problem from the solution. A domain model is supposed to be true to the problem (capture requirements from the problem domain without addressing implementation details).
领域模型在软件开发过程中仍然是一个单独的元素。这种建模方式的好处是您可以将问题与解决方案分开。域模型应该是真实的问题(从问题域中获取需求而不解决实现细节)。
Larman presents "operation contracts" as a way to assure behaviors are consistent inside a domain model. Again, contracts are supposed to be independent of a solution (an implementation). Contracts have postconditions that describe a constraint in the domain model after an operation has taken place. An example of a postcondition would be that when a customer completes a purchase in a store, the sale object is associated with each of the items the customer purchased.
Larman 将“操作契约”作为一种确保行为在域模型内保持一致的方式。同样,合约应该独立于解决方案(实现)。契约具有描述操作发生后域模型中的约束的后置条件。后置条件的一个示例是,当客户在商店完成购买时,销售对象与客户购买的每件商品相关联。
The implementation of the business logic should respect the contracts (postconditions) defined for the domain model. Larman's approach with the Controller GRASP patternas well as other GRASP patterns ends up putting this logic in various classes (usually the domain layer, which is software classes inspired by conceptual classes in the domain model) or Fa?ade (Controller) classes that handle the system operations.
业务逻辑的实现应该尊重为域模型定义的契约(后置条件)。Larman 使用控制器 GRASP 模式以及其他 GRASP 模式的方法最终将此逻辑放在各种类(通常是领域层,它是受领域模型中的概念类启发的软件类)或处理的 Fa?ade(控制器)类中系统操作。
Larman's approach is more complicated than this explanation, but the point is that behavior is never only defined alone in the domain model as methods. Larman says many times that domain (conceptual) classes do not have methods, as they are notsoftware classes.
Larman 的方法比这个解释更复杂,但关键是行为在领域模型中永远不会单独定义为方法。Larman 多次说过领域(概念)类没有方法,因为它们不是软件类。
Fowler's book also refers to another book that he wrote on Analysis Patternsfor examples.
Fowler 的书还引用了他写的另一本关于分析模式的书作为例子。
The patterns come from various domains, including health care, financial trading, and accounting. Each of the patterns is described both textually and in a simple pre-UML notation (this book was written before the UML had stabilized into a usable form).
这些模式来自各个领域,包括医疗保健、金融交易和会计。每个模式都用文本和简单的 UML 之前的符号进行描述(本书是在 UML 稳定为可用形式之前编写的)。
None of the examples in that book show software classes, that is with methods defined in a programming language (that I could find).
那本书中的示例都没有显示软件类,即使用编程语言(我可以找到)定义的方法。
I know of at least one bookwhere domain models in fields such as molecular biology have been published in UML. Here's an example (note the UML is modified -- sub-type boxes are shown in super-type boxes -- to save space):
我知道至少有一本书在 UML 中出版了分子生物学等领域的领域模型。这是一个例子(注意 UML 被修改——子类型框显示在超类型框中——以节省空间):
The book above does not model behaviors, probably because they really depend on the requirements of the software application. These models capture some business rules, such as:
上面的书没有对行为进行建模,可能是因为它们确实取决于软件应用程序的要求。这些模型捕获了一些业务规则,例如:
- Each Chemical Formulationmust be composed of 2 or more of either Chemical Elementsor Chemical Compounds, or both.
- 每个化学配方必须由 2 种或更多化学元素或化合物或两者组成。
But the models in that book are mostly data models.
但那本书中的模型大多是数据模型。
Googling will find you this huge model for the Biomedical Research Integrated Domain Group (BRIDG). Drilling down to the Molecular Biology sub-domain, and to the class Gene
, for example, you'll see it has no behavior, nor do any of the other (conceptual) classes in this domain model.
谷歌搜索会为您找到这个生物医学研究综合领域组 (BRIDG) 的巨大模型。Gene
例如,深入到分子生物学子域和类,您将看到它没有行为,该域模型中的任何其他(概念)类也没有。
Are domain models in a programming language or not?
领域模型是否是一种编程语言?
Larman's philosophy clearly shows them as programming language-independent (conceptualas opposed to softwareclasses), as a separate artifact from code, to tie them explicitly to the problem domain (requirements).
Larman 的哲学清楚地表明它们是独立于编程语言的(概念性的,而不是软件类),作为独立于代码的工件,将它们明确地与问题域(需求)联系起来。
On the other hand, you'll find Fowler saying, "I prefer POJO domain models.", which is pretty much saying domain models are defined in code.
另一方面,您会发现 Fowler 说,“我更喜欢 POJO 域模型。” ,这几乎是在说领域模型是在代码中定义的。
Eric Evans' DDDmakes the assumption that an important degree of complexity in much of software development comes from the domain, and so a model of such complex domains is essential to managing the complexity. Therefore, Domain Modeling is necessary when domains are complex. DDD suggests using a domain modeling language that is ubiquitous; that is, common to the domain experts and the developers. This would imply that in at least some cases, a domain model would not be defined in a programming language.
Eric Evans 的DDD假设很多软件开发中的一个重要程度的复杂性来自领域,因此这种复杂领域的模型对于管理复杂性至关重要。因此,当领域很复杂时,领域建模是必要的。DDD 建议使用无处不在的领域建模语言;也就是说,领域专家和开发人员共有。这意味着至少在某些情况下,领域模型不会用编程语言定义。
There is a related questionthat might shed some light (although it has generated a lot of heat). Some have criticized the question's example as being too trivial (not complex enough) for a justified domain model.
有一个相关的问题可能会有所启发(尽管它产生了很多热量)。有些人批评这个问题的例子对于一个合理的领域模型来说太琐碎(不够复杂)。
回答by David
A "domain model" is simply an object which represents some discernible concept in your business domain. A "Customer", an "Order", etc. Whatever the business logic is, the tangible entities which make up that logic are the models in your domain.
“领域模型”只是一个对象,它代表您的业务领域中的一些可辨别的概念。 “客户”、“订单”等。无论业务逻辑是什么,构成该逻辑的有形实体都是您领域中的模型。
Some will have lots of business logic (perhaps worth breaking up into other classes), some will have very little (or even none).
有些将有很多业务逻辑(也许值得分解成其他类),有些则很少(甚至没有)。
The difference between a "domain model" and any other class isn't a construct of the Java language itself, it's mainly a semantic construct of the business logic that you define.
“域模型”和任何其他类之间的区别不是 Java 语言本身的构造,它主要是您定义的业务逻辑的语义构造。