Hi!
well whatever you do, don't try it [Eiffel] now, otherwise you will go mad when you go
back to do something in Java
I agree that Java as in _the Java language_ is not always ideal and
not the most productive environment. I'm not a seasoned expert but
some experience with e.g. Smalltalk and Python has shown interesting
features (closures, mixins etc.) that Java does not have (yet) but
that are available in e.g. Ruby, Groovy etc. I still think having an
openEHR reference implementation in Java is very important, probably
the strategically most important reference implementation for openEHR.
Java as in the _JVM_ (that runs almost anywhere) and the ecosystem
around Java with a multitude of libraries and products is very
attractive. Now if we get a truly extendable and usable java-ref-impl
library it can be used smoothly with...
...several languages, e.g.:
JRuby, http://jruby.codehaus.org/
Groovy, http://groovy.codehaus.org/
Jython, http://www.jython.org/
Scala, http://scala.epfl.ch/
...and in several environments/setups, some random examples are:
http://www.terracotta.org/
http://code.google.com/webtoolkit/
http://www.springframework.org/
So let's go on discussing a bit about the future and what will be good
in order to possibly use the same java-ref-impl in many settings and
languages.
When we discussed
http://java.sun.com/j2se/1.4.2/docs/guide/lang/assert.html I
specifically mentioned what they said about using setters instead of
assertions for preconditions because I wanted a discussion on this.
Rong seems to go for what the document says and Thomas had a somewhat
different approach coming from the Eiffel culture. Below I'll try to
explain better what I think should be done and not in order to have a
solution that fits into the Java culture and that is at the same
"configurable" in some sense.
I tend to agree with Rong that in Java, the usual way to check
preconditions is to throw an exception on wrong usage. The environment
will show the caller what went wrong and where, just as I guess that
DbC preconditions in Eiffel work. Thomas said that preconditions
often are switched on in runtime (with a 5% additional processing
cost). So doing _some_ important mandatory checks in setters would
probably be a normal and good java-way of doing things. Even though
many are unnecessary when reading from database it could be an OK
default behaviour for the reference API.
If the properties are protected instead of private, then the setters
and their checks (all or selected ones) can be overridden anyway if
they are detected as significant bottlenecks in performance profiling
of some runtime system. So yes, checks in setters can be a good way to
do preconditions in java, and having protected properties instead of
private will cover the possible "configuration"-need for this.
So, what should the setters avoid as mandatory checking? I'd say
checking things in a way that forces the user to populate the objects
properties in a certain order is what should not be mandatory. The
reason is that many usages demand an arbitrary order of property
population, some persistence and GUI solutions are examples. In these
cases you might want to have the object in an illegal or inconsistent
state for a while during build up and then call validation when you
are finished. I believe Bert reported such a problem in
"AuthoredResource.java" in a posting on Jan 8.
If a certain order is demanded, then you might need to use special
builder classes (like the RM-builder) or you'll end up constructing a
parallel mutable hierarchy of custom coded objects that you then pass
to some building process (we have seen this happen here when using the
current code). If you instead have a choice to use mutable classes
that allow arbitrary population order, then coders can avoid a lot of
work. We have to consider how a library affects the users of the
library, solutions that lead to simple and elegant code within the
library but to unnecessarily complicated client code used to call the
library should be avoided.
Invariants could (depending on how they are written) cause problems
with arbitrary incremental object population. How does this look in
openEHR (the invariants in the spec)? Do they allow arbitrary order of
property population or not?
If we use assertions for invariants, they could be turned om and off
depending on what you want. The same goes for postconditions. This
would cover the "configuration" need for this part, but what do we do
if we want post-conditions on but not invariants? Any suggestions? An
extra if-statement in the assertions checking a boolean configuration
variable? (Sounds a bit too much like a "home-made-hack" maybe?)
Now, using assertions does not prevent us to also have comments
containing JML DbC rules if someone feels like adding and using that.
I do suspect that using the JML kind of DbC is not very common in the
Java culture. It sounds like Thomas has managed to get DbC used by
.net-people at Ocean, but I'd guess that is more of an exception than
a rule regarding environments that will use the java-ref-impl.
Assertions and (limited) setter checks is more java-style.
A side note to Thomas who I believe considers setters and getters are
a clumsy detour in order to change properties: Many of the alternative
JVM languages mentioned above and some scripting solutions (velocity
etc.) hide the "set" and "get" parts of java-bean-style objects and
let's your code treat the library as if the the properties are
directly accessed, but under the surface setters can do precondition
checks etc.
By the way I saw that JRuby is "Distributed under a tri-license
(CPL/GPL/LGPL)" note that CPL is the Eclipse thing. This could be
interesting to study regarding the previously mentioned Eclipse OHF. I
guess a quad licence would be quite possible too, but let's have the
IBM lawyers look at that later if necessary.
Best regards,
Erik Sundvall
http://www.imt.liu.se/~erisu/
P.s. related link:
http://www.artima.com/weblogs/viewpost.jsp?thread=173229