Re: AspectJ: solution to Java's repetitiveness?
On Apr 19, 2:50 pm, "jhc0...@gmail.com" <jhc0...@gmail.com> wrote:
I'm an experienced and multilingual programmer who, until now, avoided
becoming too familiar with Java.
While I'm very impressed with the Eclipse IDE for Java and the
performance improvements JVM has apparently made, I'm unimpressed by
the amount of error-prone boilerplate code that programming in Java
still requires.
Firstly, there is the pervasive repetitiveness of Java code. For
example, for most classes, it makes sense to define, say, clone(),
equal(), toString(), toXML(), fromString, fromXML() for all of them.
All of these operations follow a very simple pattern that can be
easily formalized. However, Java programmers have to implement each of
these methods by hand for every class. Another common example is the
trivial getters and setters.
Whenever there is repetitiveness, there is boredom, error-proneness,
job-dissatisfaction (on the part of anyone who's not a mindless drone)
and low productivity. One might argue that code generators can help
with this, but they don't help you read and modify the code.
Secondly, there is the relatively minor issue of verbosity. Consider
this fragment:
Bar b = new Bar(x, y);
Why not
b = new Bar(x, y);
If b is a member or a local variable - assign to it. If it isn't,
declare it (Note: I'm not proposing automatic member declaration, like
in Python) Following the capitalization of classes convention, one
might even trim this down to
b = Bar(x, y);
Thirdly, there is the general issue of language extension. If the
creators of the language did not implement a certain policy, such as
the automatic generation of clone(), equal(), toString(), toXML(),
fromString, fromXML(), and I would find it very useful in my project,
how could I extend the language to do these and other things for me?
(For Lisp programmers reading this, I'm basically thinking of
defmacro)
Can AspectJ address these issues?
If it can, can it do so without compromising the runtime performance
compared to writing the equivalent code by hand?
Also (and this is unrelated to the performance question), can AspectJ,
or at least its compile-time functionality be used with GWT (a Java
source to JavaScript compiler), which is my main motivation for
looking at Java?
I'll warn you - having read your further posts I consider you to be a
subtle troll. However, on the off chance that you're not, I'll give
you a straight answer: Spring AOP can, and AspectJ can, *up to a
point*.
Some languages have the concept of a mixin class. In Groovy and Ruby
they're literally called mixins; in C++, it's an application of
multiple implementation inheritance; in Objective C, they're called
categories. In all cases the effect is to add methods to a class by
applying a default implementation, which may be overridden when
needed.
Spring AOP includes the concept of "introductions", where the AOP
framework can add new interfaces, along with default implementations,
to an object. As others have already demonstrated, you can write a
bean-property-aware toString, equals, clone, etc method -- so you
could introduce this via Spring AOP and override the specific cases
where this is insufficient. The Spring manual is very cursory on this:
<http://static.springframework.org/spring/docs/2.5.x/reference/
aop.html#aop-introductions>
AspectJ supports both introductions (as introduced parent classes and
interfaces) and the addition of individual methods and fields. I
haven't played with this, but the docs are available at <http://
www.eclipse.org/aspectj/doc/released/progguide/language-interType.html>.
There are limitations on these techniques: the existing code is
unaware of the new method unless it overrides an existing method (in
which case aspect injection may be the wrong hammer for the nail), and
a generic implementation that will work on all environments will have
to content itself with manipulating objects via bean properties, not
via their members.
I also agree with the posters who say that implementing clone(), in
particular, as well as the other methods listed is rare - for
hashCode() and equals(Object) specifically it's not terribly uncommon
for objects that represent data rather than pure behaviour to have
them, but for the others I can count on one hand how often I've needed
them. Implementing methods "just in case" is a code smell;
unnecessary code is not exercised as heavily as code that's in use, so
bugs can hide in it, whereas code that doesn't exist by definition can
have no bugs. C++'s automatic generation is a problem from that angle
as you have to write code (which can be wrong) to suppress the
automatically-generated code (which *is* wrong, if you're suppressing
it).
-o