| 11-Jul-2013 | Like this? Dislike this? Let me know |
|
Money It's a gas Grab that cash with both hands and make a stash - from "Money", "Dark Side of the Moon", © 1973 Pink Floyd |
Money It's a class Make it so it's safe inside a hash - Buzz Moschetti, with apologies to Roger Waters and programmers everywhere |
Having just spent some number of weeks doing a financial services coding effort, I have reached the following conclusions about how to represent and manipulate Money in object-oriented software. I will use Java in the examples but the concepts extend to pretty much anything else out there, strict OO or otherwise.
public class Money {
private BigDecimal amt;
private String ccode;
// ..
}
double qq = 1.0 - .9;
System.out.println("qq " + qq);
// qq 0.09999999999999998<
public class Money {
private Money() {} // hide default constructor
public Money(int amt, String ccode) { // .. }
public Money(long amt, String ccode) { // .. }
public Money(String amt, String ccode) { // .. }
public Money(BigDecimal amt, String ccode) { // .. }
// NO constructor for doubles! double cannot be reliably
// ingested to BigDecimal, so just avoid them altogeher.
// ...
}
public class MoneyUtils {
/**
* Caller's choice if they want to risk the exception...
*/
public static Money add(Money a, Money b)
throws UnconvertibleCurrencyException { // ... }
/**
* Fancier versions -- but it can STILL throw an exception in case
* the table does not have the necessary conv!
*/
public static Money add(Money a, Money b, CurrencyConv cc)
throws UnconvertibleCurrencyException { // ... }
public static Money subtract(Money a, Money b, CurrencyConv cc)
throws UnconvertibleCurrencyException { // ... }
}
// In use:
import Money;
import MoneyUtils;
Money a = new Money(100, "USD");
Money b = new Money(200, "USD");
Money c = MoneyUtils.add(a, b);
Money d = new Money(200, "GBP");
CurrencyConv currtbl = factory_or_otherwise_get_it_from_somewhere();
Money e = MoneyUtils.add(c, d, currtbl);
public class Money {
public static final String USD = "USD";
public static final String JPY = "JPY";
public static final String EUR = "EUR";
public static final String GBP = "GBP";
//..,
}
// In use:
Money a = new Money(100, Money.USD);
Money b = new Money(200, Money.USD);
Money c = MoneyUtils.add(a, b);
Money d = new Money(200, Money.GBP);
Money m_a = new Money(100, Money.USD);
Money m_b = new Money(100, Money.GBP);
// Need monies normalized first....
Money m_ba = MoneyUtils.convertTo(m_b, Money.USD, currtbl);
// ... before we pull out the actual amount:
BigDecimal v_a = m_a.getAmount();
BigDecimal v_ba = m_ba.getAmount();
BigDecimal diff_v = v_a.subtract(v_ba);
if(diff_v.compareTo(BigDecimal.ZERO) < 0) {
// Do something with a negative amount...
} else {
// Not negative; rebuild a new Money:
BigDecimal c_v = new Money(diff_v, Money.USD);
}
Money m_a = new Money(100, Money.USD);
BigDecimal v_a = m_a.getAmount();
Money m_b = new Money(100, Money.GBP);
BigDecimal v_b = m_b.getAmount();
BigDecimal rate = currtbl.getConvRate(m_a.getCurrencyCode(),m_b.getCurrencyCode());
BigDecimal x = v_b.multiply(rate); // conv GBP to USD
BigDecimal diff_v = v_a.subtract(x);
if(diff_v.compareTo(BigDecimal.ZERO) < 0) {
// Do something with a negative amount...
} else {
// Not negative; rebuild a new Money:
BigDecimal c_v = new Money(diff_v, Money.USD);
}
Money m_a = new Money(100, Money.USD);
Money m_b = new Money(100, Money.GBP);
Money m_diff = MoneyUtils.subtract(m_a, m_b, currtbl);
if(m_diff.getAmount().compareTo(BigDecimal.ZERO) < 0) {
// (Maybe) do something with negative Money...
} else {
// NO need to build new Money; m_diff is already good to go!
}
/**
* Add a,b and return a new Money.
*
* In the case where currencies are not equal, the CurrencyConv
* object will be used to try to perform the conversion. The
* currency of Money a is the target and the specific conversion of
* the currency of Money b to that of Money a will be used.
* If the conversion exists,
* the new Money will be returned with currency code
* set to that of Money a. For example,
* 10 USD + 5 GBP = 17.5 USD (assuming USD<->GBP .6667)
* The UnconvertibleCurrencyException will be thrown if a specific
* conversion [from B to A] does not exist.
*/
public static Money add(Money a, Money b, CurrencyConv cc)
throws UnconvertibleCurrencyException
{ // .. }
public void addConvRate(String from, String to, BigDecimal rate, boolean permitInverse)