On 8/10/19 12:07 AM, Mathieu Lirzin wrote:
Hello Nicolas,
Hi man,
Here are a few inline comments regarding the code.
Maybe I overlooked some good reason justifying some design decision you
made, so if you want to discuss more about the suggestions I proposed,
we can do some pair programming next week.
It was a big task, so I focused my mind only on how homogenize and
centralize a number displaying. So if you I have some idea to continue
the improvement through other design concept, It's welcome :)
[...]
@@ -34,16 +34,11 @@ import java.util.TimeZone;
public final class UtilFormatOut {
public static final String module = UtilFormatOut.class.getName();
-
- // ------------------- price format handlers -------------------
- // FIXME: This is not thread-safe! DecimalFormat is not synchronized.
- private static final DecimalFormat priceDecimalFormat = new
DecimalFormat(UtilProperties.getPropertyValue("general", "currency.decimal.format",
"#,##0.00"));
-
- // ------------------- quantity format handlers -------------------
- private static final DecimalFormat quantityDecimalFormat = new
DecimalFormat("#,##0.###");
-
- // ------------------- percentage format handlers -------------------
- private static final DecimalFormat percentageDecimalFormat = new
DecimalFormat("##0.##%");
+ public static final String DEFAULT_FORMAT = "default";
+ public static final String AMOUNT_FORMAT = "amount";
+ public static final String QUANTITY_FORMAT = "quantity";
+ public static final String PERCENTAGE_FORMAT = "percentage";
+ public static final String SPELLED_OUT_FORMAT = "spelled-out";
Intuitively an ‘enum’ would seem more appropriate to make the relation
between those constants clearer.
--8<---------------cut here---------------start------------->8---
enum Format {
DEFAULT, AMOUNT, QUANTITY, PERCENTAGE, SPELLED_OUT;
// Converts a string to a typed value.
static Format valueOf(String name) {
...
}
}
--8<---------------cut here---------------end--------------->8---
Additionally I would be nice if the meaning of those “symbols” could be
documented inside the code either in the XSD with a reference in the
Java code, or in both in XSD and Java.
Indeed
private UtilFormatOut() {}
@@ -54,43 +49,70 @@ public final class UtilFormatOut {
return "";
}
- /** Formats a Double representing a price into a string
- * @param price The price Double to be formatted
- * @return A String with the formatted price
+ /** Format a number with format type define by properties
+ *
Please expand the javadoc instead of removing it.
I will check, maybe it's an error
*/
- public static String formatPrice(Double price) {
- if (price == null) {
+ public static String formatNumber(Double number, String formatType,
Delegator delegator, Locale locale) {
The dependency on the Delegator should be avoided if possible because it
makes writing unit complex tests. By the way where are those tests ? :-)
Normally not because delegator and locale are optional. If it's not the
case, I will improve it to support unit test
To remove a dependency on a class which is hard to instantiate like
‘Delegator’, the common solution is to replace it with an interface
(ideally a functional interface to let the caller pass a lambda).
In this particular case after a quick look, the ‘delegator’ argument
could potentially be replaced by a ‘templateProvider’ argument of type
‘Function<String, String>’ where the input is a format type and the
output is a template.
When things are complicated to decouple, an alternative is write an
overload specifically for the test and use it inside the coupled one.
I's seem to be a good idea :) but I'm far away to understand what do you
explain, I need to studies more ^^
+ if (number == null) {
return "";
}
- return formatPrice(price.doubleValue());
+ if (formatType == null) {
+ formatType = DEFAULT_FORMAT;
+ }
+ if (locale == null) {
+ locale = Locale.getDefault();
+ }
Does silencing ‘null’ values really make sense here? if ‘null’ values
doesn't have sound meaning, I would recommend bailing out early instead
of silencing a possible programming mistake or worse let another method
downstream throw a cryptic exception later. To bail out early you can
use things like ‘Objects.requireNonNull(myArg)’.
I use the silencing because we are on displaying number so instead
deploy complex analyze with risk to break something during the
rendering, I prefer to use safe call en just return empty String.
Have a nice weekend!
Thanks for your time and remarks
Nicolas