0

In my application I often have the case where the same data needs to be in different format in different places. For example a number has to be sent to a web service in decimal form, but has to be formatted in a specific way for the user to see.

public class Prize {
   float prizeAmount;
}

A webservice expects the amount to be in the format:

A: 12000000

The user expects to see the amount in the format:

B: 12. Mio €

How can I implement this in a reusable way? I could save the data in format A, then format it to B in the view class. But then what if it is shown in several views? Then I need to implement the formatter multiple times. Is there an elegant pattern I can apply to this?

  • 3
    Possible duplicate of Choosing the right Design Pattern – gnat Jul 28 '17 at 10:10
  • 3
    "Then I need to implement the format multiple times." -- This should be a big hint about how to proceed. What do you do with other code that's going to be used in more than one place? – Blrfl Jul 28 '17 at 10:22
  • 1
    @dan DRY. – Glorfindel Jul 28 '17 at 10:47
  • 2
    This could be a "model" and "view" problem. That is, your A:12000000 is the model data, and the representation B: 12. Mio € is the view. – Fuhrmanator Jul 28 '17 at 15:48
  • 2
    Using single precision binary floats for money. shudder – CodesInChaos Jul 30 '17 at 11:09
2

Remember that patterns are not magical recipes. There's no pattern for every single problem. And not every problem respond to a pattern.

In this specific case, as @Mike Nakis already pointed out, the problem could be the way you are expressing the concept Price. It lacks on meaningful information and valuable resources. For example, even the Webservice's consumer might need to know the currency or the amount in its read-only format. Isn't it? Right now, Price is only wrapping a float.

What if we provide it with some more relevant information?1. For example

public class Prize {
   BigDecimal amount;
   Locale locale;

   public BigDecimal getAmount(){ ... }

   public String getCurrencyCode(){
      return Currency.getInstance(locale).getCode();
   }
   public String getCurrencySymbol(){
      return Currency.getInstance(locale).getSymbol();
   }
   public String getFormattedAmount(){
      return DecimalFormat.getCurrencyInstance(locale).format(amount);
   }
}

Now, Price is capable of transferring any piece of info that users / webservices might need to know. For example, sending getAmount alongside with getCurrencyCode allow consumers to do currency conversions. On the other hand, If we don't want consumers to modify the amount or its representation, we could send only the getFormattedAmount.

Back to the main question, due to the Price itself is capable of transferring its representantation in different ways, we don't need to copy-paste the transformations all over the code.


1: This approach could take you to save the locale or the currency too. According to the Java API, Locale seems to me a more valuable info to persist than currency code. Or save both.

For further information about Currency, check out the API Doc.

1

Separate the internal and external representation. Choose an internal format and use that throughout all internal code. Only when data goes outside, generating a web page or calling an external service transform it into the required representation.

The same goes for incoming data, transform it to the internal format at the border.

Oh, and don't use a float for a price to prevent rounding errors on calculations (tax/price reduction in %).

0

Look into the MVC pattern. This is where you have a Model which will store the number how your webservice expects. A view which shows it in the form the user expects to see it. Then the Controller for doing the conversion.

There are many patterns for doing this sort of thing as well such as MVVM, MVP or the general term now MV something. Read up on them and choose what is best for your situation.

  • 3
    The MVC pattern doesn't have anything to do with this, except for the principle of display format vs. storage format, a principle not unique to MVC. – Robert Harvey Jul 29 '17 at 19:27
0

As you have probably figured out by now, there is no pattern for this. Patterns are for other stuff. You would have avoided annoying people if you had just skipped the word "pattern" and used some other word, like "technique".

But I digress.

Your data needs to be stored in the most appropriate format for representing that kind of data.

That having been said, be advised that float is a bit too small when your values are going to be as large as 12000000. A float only has 6 significant digits, and 12000000 is 8 digits, which means you are in trouble. Consider using BigDecimal instead, or perhaps even long as a number of cents rather than number of euros.

Then your data needs to be converted to and from whatever formats are required for representation or transmission. There is no way around that.

  • Actually, people shouldn't be encouraged to use double for monetary amounts, as a value of 0.01 cannot be accurately represented. BigDecimal could do it, but my approach is to multiply the value by 100 to obtain value in pennies, and use long for representing the penny amount. In database, I use numeric(15,2) which can represent even pretty large monetary amounts. – juhist Jul 30 '17 at 13:28
  • @juhist you are right, I corrected. – Mike Nakis Jul 30 '17 at 13:38
  • 1
    The word pattern attracts "annoying" people like me because people who ask "which one should I use" invariably lack the skills to use it properly. See also meta.stackexchange.com/a/142354 – Robert Harvey Jul 30 '17 at 14:39
  • @RobertHarvey "annoying" here was a verb, not an adjective. – Mike Nakis Jul 30 '17 at 14:54
  • Ah. Mea culpa.. – Robert Harvey Jul 31 '17 at 0:43
0

This is a more general question than most of the answers address. From an OO perspective you need a formatter class for your data type. For basic value types you will find though that the class library of your favorite programming language already offers nice formatting options, if they are not already offered by the value class itself (like String.Format() in .net). For your own custom types you will have to roll your own formatters. Or, if you do not expect to be needing too many different or complicated presentations, just create a couple of AsXyz methods.

-2

You could use Factory Pattern

You have your PrizeClass in an normal format, an int or float, then depending on who is asking for this data through a factory you get the corresponding Prize Formatter, each formatter just formats the data in the needed way.

For example: - PriceWithTextFormatter - PriceWithSymbolFormatter

And so on.

  • why is this downvoted? – redigaffi Sep 7 '17 at 10:12

protected by gnat Jul 30 '17 at 16:58

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.