That’s a good point. Agreed, my solution does not actually fix anything :)
This is the first time I’ve really thought about how easy it is to abuse interfaces. I suppose this applies to any value carrying type.
From: jodastephen@... [mailto:jodastephen@...] On Behalf Of Stephen Colebourne
Sent: 29 January 2013 10:39
Subject: [JSR-354] Re: SE, ME, EE or what
I don't think you've fixed that here. Anybody can still implement the interface independently of this factory, so unknown/malicious implementations can still be introduced.
BTW, interfaces will have static methods in JDK 1.8, so factories like this will die.
To be clear, the JSR does need interfaces for the major concepts Money/Currency. My point is that the core and most important things are the value types, and getting users to create and pass those around is highly desirable. Note that this does not preclude users writing their own value type implementing the interface and passing that value type around.
LIke all things, this is a balance as well. For example, JSR-310 accepts the interface as input to the formatter, and that would make sense here too.
On 29 January 2013 09:15, Jeremy <jerdavies@...> wrote:
I see your point Stephen - sounds like you've found out the hard way on this.
One thing to consider here is that we may well be able to have our cake and eat it by ensuring the value type object creation is strictly managed using the appropriate factory/builder pattern/fluent interface.
final FooInterface immutable = FooFactory.create()
This way you can be sure the interface returned is immutable and has member variable data domains to be exactly what you require (you could force the implementor to pass concrete value types as parameters, not interfaces, for instance).
I see the flaw in having interfaces which have no guarantees as to the constituent class structure, but does this approach not fix that?
From: Werner Keil [mailto:werner.keil@...]
Sent: 28 January 2013 23:21
Well as said before, if everyone agrees (and there has been almost a year wasted with discussions like those) on a single Money class, that one could be final in a RI.
Currency while it was defined final suffers from being unusable for custom currencies and there are plenty of cases, not just BitCoins or other virtual currencies that companies keep using day in day out.
Hence in many projects dealing with monetary amount people simply put a String for the currency code and the numeric value of their choice together ignoring java.util.Currency because the custom or totally different codes they need in their DB would simply throw an exception if they used it
People can and will use code like that
Temporal t = LocalDate.now() (assuming the API in OpenJDK remains somewhat stable) and at least in theory nobody keeps them from implementing Temporal another way they want or need. At least with the Chrono abstract class and national calendars this is even highly recommended to happen.
On Mon, Jan 28, 2013 at 11:33 PM, Stephen Colebourne <scolebourne@...> wrote:
On 28 January 2013 21:22, Jeremy <jerdavies@...> wrote:
> I recently joined the EG on JSR-354. I agree with your points but can you
> clarrify what you mean by:
> it is vital that users write Money m = Money.of(...) and not Monetary m =
> Money.of(...) This is necessary to ensure the objects passed about are
> immutable and behave correctly.
> How does this have a bearing on the immutable object contract? Passing the
> concrete object around, not the interface does not feel right but I'm
> guessing this is specific to the "money" example mentioned.
Imagine you write a method performing money calculations. You have three options
public Money process(Money)
public Money process(Monetary)
public Monetary process(Monetary)
The second two suffer from the problem that in Java, an interface (or
abstract class) guarantees you nothing. Only a class has the
guarantees you need wrt immutability. (An interface can specify that
implementations should be immutable, but it cannot guarantee it.)
The return type should also be a concrete class, again to ensure that
users know what they are getting.
A classic example of this going wrong is BigDecimal. That is a class,
but it is not final. Most users writing an API with a setter method
accepting a BigDecimal and storing it in an instance variable will
simply assign the object to the internal state. But this is a security
hole and potential bug. The user of the the API can maliciously pass
in a BigDecimal subclass and gain access they shouldn't. Given the
sensitive nature of most money calculations, this must be avoided.
As an aside, part of this is knowledge from experience. JSR-310
originally had interfaces like DateProvider and TimeProvider that were
used as the inputs to most methods as a means of flexibility for
users. This turned out to be a hugely bad idea. The examples would
take a long time to work through, but in summary the problem was that
DateProvider would only take the LocalDate part of an object, whereas
the object you were passing to the method might be something more
complex, like a date-time with time-zone. What happened was that you
looked at a piece of code and thought it would take the date, time and
time-zone from the input object, where in fact it was only taking the
date. This design of flexible inputs turns out to be a similar one to
Scala's implicits, which are frequently too lenient.
The above describes why you want methods to generally be quite
specific, and the same applies to local variables. The Java code we
are going to be writing going forward will be increasingly parallel. A
Monetary interface object can provide no real guarantees about how it
will behave in parallel, whereas an honest, clean immutable value type
is crystal clear.
On 28 January 2013 22:18, Werner Keil <werner.keil@...> wrote:
> Sorry, but assuming Money is a concrete class implementing a Monetary
> interface, this is bullshit, and the person who recommends using interfaces
> over classes isn't just me but Josh Bloch in his book Effective Java (he
> also was main author of some of the more easily to extend parts of the JDK
> like Collection API)
This is why I listed in my previous email that it is important to
understand that designing this API is very different to designing a
typical enterprise API, or even Collections. These types
(date/money/currency) are only one level above Integer and String.
They have to perform in the same way, and that means that they have
very a different API style. Josh Bloch's guidelines are more intended
for general API design, not value type design. He also says "favour
composition over inheritence".
Except in one or two cases where those "Localizable" subinterfaces use inheritence, most parts of the spec apply this, e.g. Converters and ExchangeRate, money itself is already a composite type.
Some of the problems of Number being an abstract class rather than interface, Josh also outlined in those chapters.
The equivalent to Monetary (or MonetaryAmount, at least so far there's a helper class with the same name in the JSR) is Temporal, and if you hate interfaces so much, why would that still be an interface see above?
A base representation of a temporal object, such as a date, time, offset or some combination, that is complete enough to be manipulated using plus and minus.
The entire package says ...systems other than the default ISO.
Well, that's pretty much what the Money JSR also needs to acomplish beside default implementation for ISO, one for Currency already exists, unless let's say a "java.money" package really needed to do this all over again?
If Temporal as opposed to TemporalUnit was a security risk, then why does it exist?