A simple example: anemia model or domain model

Source: Internet
Author: User
Tags java web

from: http://www.iteye.com/topic/283668


Recently, Taowen has launched two consecutive discussions on anemia models and field models, which has aroused extensive and heated discussion, but I think it is debatable what the outcome of the discussion (or controversy) is. The problem is that the anemia model and the domain model have their own views, if there is no consensus on this concept, then the outcome of the discussion should be conceivable, the discussion of the harvest is also some, at least know the existence of differences. To make the problem deterministic, I would like to start with a simple example, using my concept of the anemia model and the domain model to implement the example separately. As to whether my understanding is correct or not, we can make a judgment, at least there is a criterion that can be judged here.

An example


I would like to cite an example of a bank transfer and another example of abuse. But even if this example is not what you think it is, it's the example of plagiarism in the <<pojos in action>>, forgiving my poor imagination. When money is transferred from one account to another, the amount of the transfer can not exceed the balance of the first account, the total balance can not be changed, the money is only from one account to another account, so they must be completed within a transaction, each successful completion of the transaction to record the transfer transaction, this is all the rules.

anemia Model


We first use the anemia model to achieve. The so-called anemia model is a complete association between the model objects (there may be redundant associations), but there is almost no other way to object except get and set nowhere, the whole object acts as a data container, which is a structure in C language. All business methods are implemented in a stateless service class, and the service class contains only a few behaviors. This is the most common development model used by Java Web applications, and you may be using this approach, although it may not be known that it has a &ldquo; anemia model &rdquo;, thanks to Martin Flower, who is accustomed to inventing terminology. )。

Package Structure


Before we discuss the specific implementation, we'll look at the package structure of the anemia model to get a general idea.


The implementation of the anemia model generally includes the following packages: DAO: Responsible for persistent logical model: Contains Data objects, service-manipulated object service: Place all service classes that contain all the business logic facades: Provide access to the UI layer

Code Implementation


First look at the two classes of the model package, account and Transfertransaction objects, representing accounts and a transfer transaction, respectively. Since they do not contain business logic, they are a normal Java Bean, and the following code omits the Get and set methods. Java code   public class account {       private String  AccountId;        private BigDecimal balance;           public account ()  {}         public account (string accountid, bigdecimal balance)  {            this.accountId = accountId;            this.balance = balance;        }        // getter and setter        }  

public class Account {private String accountid;

	Private BigDecimal balance;
		Public account () {} public account (String AccountId, BigDecimal balance) {this.accountid = AccountId;
	This.balance = balance; }//Getter and setter ...} 

  Java code   public class transfertransaction {       private  Date timestamp;        private String fromAccountId;        private String toAccountId;        private BigDecimal amount;             public transfertransaction ()  {}            public transfertransaction (String fromaccountid, string toaccountid, bigdecimal  amount, date timestamp)  {            this.fromaccountid = fromaccountid;            this.toAccountId = toAccountId;            this.amount = amount;            this.timestamp = timestamp;       &nbsp}           // getter and  setter    }  

public class Transfertransaction {private Date timestamp;
	Private String Fromaccountid;
	Private String Toaccountid;	

	Private BigDecimal amount;  Public transfertransaction () {} public transfertransaction (string Fromaccountid, String toaccountid, BigDecimal amount,
		Date timestamp) {this.fromaccountid = Fromaccountid;
		This.toaccountid = Toaccountid;
		This.amount = amount;
	This.timestamp = timestamp; }//Getter and setter ...} 


These two classes have nothing to say, they are some data containers. Next look at the Transferservice interface in the service pack and its implementation transferserviceimpl. Transferservice defines the interface of the transfer service, and Transferserviceimpl provides the implementation of the transfer service. Java code public interface Transferservice {transfertransaction Transfer (string Fromaccountid, String Toaccountid,    BigDecimal amount) throws Accountnotexistedexception, accountunderflowexception; }

Public interface Transferservice {
	transfertransaction Transfer (String Fromaccountid, String Toaccountid, BigDecimal amount) 
			throws Accountnotexistedexception, accountunderflowexception;

  Java code   public class transferserviceimpl implements transferservice {        private AccountDAO accountDAO;        private TransferTransactionDAO transferTransactionDAO;           public transferserviceimpl (Accountdao accountdao,                   Transfertransactiondao transfertransactiondao)  {            this.accountDAO = accountDAO;            this.transferTransactionDAO =  Transfertransactiondao;           }           public  Transfertransaction transfer (String fromaccountid, string toaccountid,    &NBSP;&NBsp;          bigdecimal amount)  throws  accountnotexistedexception, accountunderflowexception {            validate.istrue (Amount.compareto (Bigdecimal.zero)  > 0);                      account fromaccount =  accountdao.findaccount (Fromaccountid);            if  (fromaccount == null)  throw  new accountnotexistedexception (Fromaccountid);            if  (Fromaccount.getbalance (). CompareTo (Amount )  {                 < 0) Throw new accountunderflowexception (Fromaccount, amount);            }                       account toaccount = accountdao.findaccount (Toaccountid);            if  (toaccount == null)  throw  new accountnotexistedexception (Toaccountid);            fromaccount.setbalance (Fromaccount.getbalance (). Subtract (amount));            toaccount.setbalance (Toaccount.getbalance (). Add ( Amount);                               accountdao.updateaccount (fromaccount);       //  It's not necessary for hibernate             accountdao.updateaccount (Toaccount);        //  for hibernate this is not a necessity            return  transfertransactiondao.create (Fromaccountid, toaccountid, amount);        }   }  

public class Transferserviceimpl implements Transferservice {private Accountdao Accountdao;

	Private Transfertransactiondao Transfertransactiondao;  Public Transferserviceimpl (Accountdao Accountdao, Transfertransactiondao transfertransactiondao) {This.accountDAO =
		Accountdao;

	This.transfertransactiondao = Transfertransactiondao; Public transfertransaction Transfer (string Fromaccountid, String toaccountid, BigDecimal amount) throws Accountnote		

		Xistedexception, accountunderflowexception {validate.istrue (Amount.compareto (Bigdecimal.zero) > 0);
		Account Fromaccount = Accountdao.findaccount (Fromaccountid);
		if (Fromaccount = = null) throw new Accountnotexistedexception (Fromaccountid);
		if (Fromaccount.getbalance (). CompareTo (amount) < 0) {throw new accountunderflowexception (Fromaccount, amount);
		Account Toaccount = Accountdao.findaccount (Toaccountid);
		if (Toaccount = = null) throw new Accountnotexistedexception (Toaccountid); Fromaccount.setbaLance (Fromaccount.getbalance (). Subtract (amount));				

		Toaccount.setbalance (Toaccount.getbalance (). Add (amount));		Accountdao.updateaccount (Fromaccount);		For hibernate this is not a necessary accountdao.updateaccount (Toaccount);
	For hibernate, it's not necessary. Return Transfertransactiondao.create (Fromaccountid, Toaccountid, amount);
 }
}


The Transferserviceimpl class uses Accountdao and Tranfertransactiondao, and its transfer method is responsible for the entire transfer operation, which first determines that the amount of the transfer must be greater than 0, Then Judge Fromaccountid and Toaccountid is an existential account of the accountid, if there is no cast accountnotexsitedexception. Then determine whether the transfer amount is greater than the fromaccount balance, if it is thrown accountunderflowexception. The setbalance of Fromaccount and Toaccount are then separately called to update their balances. Finally, save to the database and record the transaction. Transferserviceimpl is responsible for all business logic and verifies that the account balances are exceeded and updated. Everything is not complicated, and for this example the anemia model works very well. This is because the example is fairly simple and the business logic is not complex, and once the business logic becomes complex, the Transferserviceimpl expands.

Pros and cons

The advantages of the anemia model are obvious: Many programmers have mastered this model, and for beginners, this model is natural and even considered by many to be the most orthodox model in Java. It is very simple, and it works very well and develops very quickly for the less complex business (transfer business). It also does not seem to require a full understanding of the domain, as long as it gives each step to implement the function, it can be implemented. Transaction boundaries are fairly clear, and each method of service generally can be viewed as a transaction, since each method of service usually corresponds to a use case. (In this example I used a façade as a transaction boundary, which I would say is superfluous)


The downside is also obvious: all business is handled in service, and as the industry becomes more complex, service becomes more and more large and ultimately difficult to understand and maintain. Putting all the business in a stateless service is actually a procedural design that has a natural disadvantage in organizing complex business, and as the business is complex, the business is duplicated across multiple methods in the service. When you add a new UI, a lot of business logic has to be written back. For example, when a Web service interface is to be provided, the service originally provided for the Web interface is difficult to reuse, resulting in repetitive business logic (which can be seen more clearly in a hierarchical diagram of the anemia model), and how to keep business logic consistent is a big challenge.


Domain Model


Next look at the domain-driven model, in contrast to the anaemia model, the domain model takes on the key business logic, the business logic is distributed among the multiple domain objects, and the service only completes some business logic that is not appropriate for the model, it is a very thin layer that directs multiple model objects to complete the business functions.

Package Structure

The implementation of the domain model generally includes the following packages: Infrastructure: Represents the infrastructure layer, generally responsible for the persistence of objects. Domain: Represents the domain layer. The domain package includes two sub packages, which are model and service. The model contains the models object, the Repository (DAO) interface. It is responsible for the key business logic. Service packs are a series of domain Services that require service, according to DDD, because some of the concepts in the domain are inherently behavioral and inconvenient to be placed in a model object. For example, the transfer operation, which is a behavior, and it involves three objects, Fromaccount,toaccount and transfertransaction, it is not good to put it into any object. Application: Represents the application layer, which primarily provides a unified access interface to the UI layer and serves as a transaction boundary.


Code Implementation

Now see implementation, as usual first look at the object in model: Java code   public class account {        private string accountid;        private BigDecimal balance;                private OverdraftPolicy  overdraftpolicy = nooverdraftpolicy.instance;                public account ()  {}                 public account (String accountid,  bigdecimal balance)  {            Validate.notempty (AccountId);            validate.istrue (balance == null | |  balance.compareto (Bigdecimal.zero)  >= 0);                        this.accountid = accountid;            this.balance = balance == null  ? BigDecimal.ZERO : balance;       &nbsp}                 Public string getaccountid ()  {            return accountid;       &nbsp}           public bigdecimal  getbalance ()  {           return balance;       &nbsp}                 Public void debit (bigdecimal amount)  throws accountunderflowexception {            validate.istrue (Amount.comparETo (Bigdecimal.zero)  > 0);                         if  (!overdraftpolicy.isallowed (this, amount))  {                throw new accountunderflowexception (this,  Amount);            }             balance = balance.subtract (amount);       &nbsp}                 Public void credit (bigdecimal amount)  {            validate.istrue (Amount.compareto (Bigdecimal.zero)  > 0);                         balance = balancE.add (amount);       &nbsp}           }  

public class Account {private String accountid;
	
	Private BigDecimal balance;
	
	Private Overdraftpolicy overdraftpolicy = nooverdraftpolicy.instance;
		Public account () {} public account (String AccountId, BigDecimal balance) {validate.notempty (accountid);
		
		Validate.istrue (balance = = NULL | | | Balance.compareto (BIGDECIMAL.ZERO) >= 0);
		This.accountid = AccountId; This.balance = Balance = = null?
	BigDecimal.ZERO:balance;
	Public String Getaccountid () {return accountid;
	Public BigDecimal GetBalance () {return balance; public void Debit (BigDecimal amount) throws Accountunderflowexception {validate.istrue (Amount.compareto (BigDecimal .
		
		ZERO) > 0);
		if (!overdraftpolicy.isallowed (this, amount)) {Throw to New accountunderflowexception (this, amount);
	} balance = Balance.subtract (amount);
		
		} public void Credit (BigDecimal amount) {Validate.istrue (Amount.compareto (Bigdecimal.zero) > 0);
	Balance = Balance.add (amount);
 }
	
}


The difference from the anaemia model is that the account class contains the business method (Credit,debit), noting that there is no set method, and that the update to account is updated by the business method. Since "It is not allowed to withdraw money from an account that is greater than the balance of deposits" is an important rule, placing it in a separate interface Overdraftpolicy provides the flexibility to change the implementation when the business rules change.

Transferserviceimpl class: Java code   public class transferserviceimpl implements  transferservice {       private AccountRepository  Accountrepository;        private TransferTransactionRepository  Transfertransactionrepository;                public transferserviceimpl ( accountrepository accountrepository,                  transfertransactionrepository transfertransactionrepository)  {           this.accountRepository = accountRepository;            this.transferTransactionRepository =  Transfertransactionrepository;       &nbsp}                 public transfertransaction transfer (string fromaccountid, string  Toaccountid,                bigdecimal  amount)  throws accountnotexistedexception, accountunderflowexception {           Account fromAccount =  Accountrepository.findaccount (Fromaccountid);            if  (fromaccount == null)  throw  new accountnotexistedexception (Fromaccountid);            Account toAccount =  Accountrepository.findaccount (Toaccountid);            if  (toaccount == 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.