tags:

views:

84

answers:

6

Hi,

I've got a value object, which stores info for example amount. The getAmount() getter returns amount in cents. However in various places, we need to get amount in dollar. There are 2 approaches I can think of:

  1. write a convert method and place it in a utility class.
  2. add a getAmountInDollar() getter in the value object.

I prefer the second approach. What do you think? What are pros and cons of both approaches?

+1  A: 

That's a bit a matter of taste. But, in my opinion, if this information is irrelevant to the model in question, then I'd prefer the first approach. It keeps the model clean and the other benefit is that it's reuseable for all other values of that kind. It would be much nicer as well if you make the currency type another argument of that utility method, this way it's even more flexible. Hint: NumberFormat.

BalusC
I got your point. Thanks!
sarahTheButterFly
A: 

Because encapsulation is about data and behaviour in a "black box" scenario, I prefer the second also, for object-oriented persuasion.

John K
Yes, that was my initial thought too. But after read Kevin and BalusC's comments, I will go approach 2.
sarahTheButterFly
@sarah: You're not the only one :)
John K
A: 

I like option 1, so it can be used on any value that may be in cents, not just that specific field in that specific class. It leaves the option to be used elsewhere in your code without code duplication.

Kevin Crowell
+1  A: 

I prefer to keep the public API of a class fairly focused. Once you start adding methods to it that are not part of the "core" you run the risk of having a very complex beast. In the case of a class that pretty much just holds data I would strive to keep it that way.

In the end there is no clear cut "best" answer... it just goes based on your personal experience. Mine says once you start "polluting" the API it is hard to stop, and eventually you need to break the class up anyways.

The utility class also gives you a place to put other related, but not quite, methods that you will probably find over time.

If you goal is to reduce the number of classes, I would say not to. If you feel that having the method in the class makes the code "cleaner" than do it that way.

TofuBeer
Thanks. I will remember not to 'polluting' the API.
sarahTheButterFly
+2  A: 

To be honest I'm struggling with this because I think money ought to always be represented as a decimal, used as a decimal internally, then formatted as needed on output. So I'd probably handle the dollar/cents issue in the output formatter.

If I needed to handle conversions to other monetary units, then I'd create a Money class and return it as that with the Money class containing the amount and unit information (and presumably a connection to a service to be used for conversions as needed).

tvanfosson
I don't think you understood what the poster was asking. When she said "I've got a value object", I think she was saying that she has a Money class and is wondering how to get the information out of it. Should she have a `getAmountInDollars()` and `getAmountInEuros()`? Or should she just have a `getAmount()` and let the consumer call `convertToDollars()` or `convertToEuros()`?
Gabe
That's certainly possible. I was assuming that is was simply a container class for a variety of data, including an amount (perhaps, price).
tvanfosson
Yes gabe, you are right. That's exactly what I was asking.
sarahTheButterFly
I actually prefer storing in cents. That way for most calculations you do with money you will not run into floating point oddities. Of course if you need to multiply by a fractional amount or divide then you have to handle it anyway so I guess neither way is perfect.
@kennygrimm -- I'm suggesting decimal, not floating point.
tvanfosson
+3  A: 

I think it might be better to generalize your getter with an overload that indicates what units, so I could call getAmount() to get the default, but getAmount(Units.Dollar) or getAmount(Units.Euro) would also be available without having to create a new getter for every possible currency conversion.

Of course this generalizes even further so you could have a temperature value stored internally in Kelvins, but could allow getAmount(Units.Celsius) or getAmount(Units.Rankine) to get the temperature in other scales.

Gabe
Thanks! Didn't expect to learn so much by just asking such a small question. :)
sarahTheButterFly
this is the approach I prefer, and I like the idea of writing it as getAmount(Locale). The nice thing about this, is that you can modify the getAmount method to return other things, without bloating the API too much.
David