IT tutorials
 
Database
 

Oracle Coherence 3.5 : Implementing Domain Objects - Domain model building blocks (part 2)

1/3/2013 11:39:52 AM
- Free product key for windows 10
- Free Product Key for Microsoft office 365
- Malwarebytes Premium 3.7.1 Serial Keys (LifeTime) 2019

2. Value objects

Unlike entities, value objects are not uniquely identifiable within a system. They simply represent values from the domain, and are typically immutable (and if they are not, they probably should be). An example of a value object might be a Money object, representing monetary amount, or an Address object, representing a mailing address of a person or a company, and defined by attributes such as street, street number, city, state, postal code, and country.

The value objects are typically used as attributes of entities. That means that they won't have their own cache, but will be stored as part of an entity's serialized state, within the cache for an entity they belong to. For example, our Account entity has a balance attribute represented by the Money value object, which will be serialized and stored with the rest of the account's state.

Implementing the Money value object

It is amazing that there is no built-in Money class in standard class libraries in either Java or .NET, especially considering the fact that most applications deal with monetary values one way or another.

However, that might work to our advantage in this case, as it gives us the opportunity to create a portable implementation of Money in Java, .NET, and C++. In this section, we will look at the Java implementation, but the other two are available within the sample application if you would like to see the details.

The Money class is an immutable class that simply encapsulates the amount and currency attributes:

public class Money implements Serializable {
private final BigDecimal m_amount;
private final Currency m_currency;
public Money(BigDecimal amount, Currency currency) {
m_amount = amount.setScale(
currency.getDefaultFractionDigits(),
RoundingMode.HALF_EVEN);
m_currency = currency;
}
public BigDecimal getAmount() {
return m_amount;
}
public Currency getCurrency() {
return m_currency;
}
}

In addition to the constructor shown earlier, the class also provides a number of convenience constructors that allow you to specify the amount as a string, integer, or floating-point value, and currency either as a currency code or an actual java.util.Currency instance.

However, the main reason for creating the Money class is not to capture its attributes, but to define the behavior applicable to monetary values:

public class Money implements Serializable {
...
public boolean isSameCurrency(Money money) {
return m_currency.equals(money.m_currency);
}
public Money add(Money money) {
checkCurrency(money);
return new Money(m_amount.add(money.m_amount), m_currency);
}
public Money subtract(Money money) {
checkCurrency(money);
return new Money(m_amount.subtract(money.m_amount), m_currency);
}
public boolean greaterThan(Money money) {
checkCurrency(money);
return m_amount.compareTo(money.m_amount) > 0;
}
public boolean lessThan(Money money) {
checkCurrency(money);
return m_amount.compareTo(money.m_amount) < 0;
}
}


					  

This gives us everything we need to work with monetary values within our application, and ensures that currency is taken into account when performing arithmetic operations or comparisons on two monetary values.

Value objects as identifiers

Value objects can also be used as identifiers for an entity; while they don't have an identity themselves, they are often used to represent composite identifiers containing two or more entity attributes. An example of such a value object is the Transaction.Id class we created earlier.

While in most cases all that Coherence cares about is that value objects are serializable, when they are used as identifiers you also need to ensure that they implement the equals and hashCode methods properly, and that the serialized binary form of equivalent value objects is identical.

This is very important, because key-based lookups against the Coherence cache depend on either standard object equality, or the binary equality of serialized keys. The exact requirement varies based on how objects are stored internally within the cache, but as a best practice, you should ensure that your identity object's serialized form is always consistent with equals. That way you won't have to worry about the details regarding the internal behavior of the cache type you are using.

Broken keys

I cannot stress the importance of this enough, as I have seen time and time again broken implementations of key classes, which have caused a lot of headache and wasted time.

By far the most common reason for broken keys is the omission of non-transient fields in the implementation of the equals method, so make sure that doesn't happen to you-if the field is serialized, it should be used for comparison within the equals implementation as well.


Services

In a rich domain model, the best places to put business logic are the domain objects that the behavior naturally belongs to, such as entities and aggregates. However, in most applications there is some behavior that doesn't clearly belong to any of the data objects. In such cases, you can define services within the domain itself that implement the necessary logic.

These domain-layer services are not the same as the course-grained services most of us got accustomed to while building applications using session EJBs. They are much lighter and much more focused, usually encapsulating only a handful of business methods, and very often only one or two.

You will typically still have a set of coarse-grained services within the orchestration layer, that are used to coordinate multiple activities within the domain layer and transform output into the most appropriate format for the presentation layer. They can also come in handy as a boundary for some of the infrastructure-level services, such as transactions and security.

However, the big difference between these orchestration-layer services and the services most of us used to implement using session beans is that session beans tended to contain most, if not all of the business logic, making domain objects dumb data holders in the process. The orchestration-layer services, on the other hand, are there purely for coordination and boundary definition purposes, while the business logic is implemented within the domain model.

Implementing the CurrencyConverter service

A good example of a domain service is the CurrencyConverter we defined within our domain model. The conversion logic clearly doesn't belong to the Account, so introducing a service whose only responsibility is to perform currency conversions makes perfect sense.

The best way to implement services in general is to hide the implementation behind an interface. That way the implementation can be easily replaced without any impact on the service clients.

We will follow that approach and define a CurrencyConverter interface:

public interface CurrencyConverter {
CurrencyConversion convert(Money amount,
Currency targetCurrency);
}

As you can see, the interface is quite simple-it defines a single method that accepts the amount to convert and target currency as arguments and returns a CurrencyConversion value object:

public class CurrencyConversion {
private final Money m_originalAmount;
private final Money m_convertedAmount;
public CurrencyConversion(Money originalAmount,
Money convertedAmount) {
m_originalAmount = originalAmount;
m_convertedAmount = convertedAmount;
}
public Money getOriginalAmount() {
return m_originalAmount;
}
public Money getConvertedAmount() {
return m_convertedAmount;
}
public BigDecimal getExchangeRate() {
BigDecimal exchangeRate =
m_convertedAmount.getAmount()
.divide(m_originalAmount.getAmount());
return exchangeRate.setScale(4, RoundingMode.HALF_EVEN);
}
}

Finally, we have a service implementation that looks up the exchange rate for the requested conversion and performs the conversion. The actual implementation is not that important for the further discussion and is available in the sample code download, so I will omit the code in order to save some trees.
 
Others
 
 
 
Top 10
 
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 2) - Wireframes,Legends
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 1) - Swimlanes
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Formatting and sizing lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Adding shapes to lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Sizing containers
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 3) - The Other Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 2) - The Data Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 1) - The Format Properties of a Control
- Microsoft Access 2010 : Form Properties and Why Should You Use Them - Working with the Properties Window
- Microsoft Visio 2013 : Using the Organization Chart Wizard with new data
Technology FAQ
- Is possible to just to use a wireless router to extend wireless access to wireless access points?
- Ruby - Insert Struct to MySql
- how to find my Symantec pcAnywhere serial number
- About direct X / Open GL issue
- How to determine eclipse version?
- What SAN cert Exchange 2010 for UM, OA?
- How do I populate a SQL Express table from Excel file?
- code for express check out with Paypal.
- Problem with Templated User Control
- ShellExecute SW_HIDE
programming4us programming4us