AspectJ: solution to Java's repetitiveness?

J

jhc0033

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?
 
A

Arne Vajhøj

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.

Those methods are not implemented for most Java classes.
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.

Getter and setter code can be generated by your IDE (if not then
switch to another IDE).
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);

That would not be Java.
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?

AspectJ can extend a group of classes with certain functionality.

I don't think you will want to do what you are describing.

And I doubt that AspectJ can do the specific extensions
you want.
If it can, can it do so without compromising the runtime performance
compared to writing the equivalent code by hand?

AspectJ weaved in aspects add some overhead, but are still reasonable
fast.
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 don't think so. AspectJ is for Java byte code. GWT generates
JavaScript.

Arne
 
E

EricF

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?

AspectJ will not address those issues. It's best for cross-cutting concerns,
code that might be common across methods - logging, timing, and transactions
are frequent examples.

Java is a bit verbose. As others have noted, a good ide can handle the
getters/setters, toString, equals, etc. You might want to look at Groovy,
which is a dynamic language based on Java that runs in the JVM. Actually
Groovy sounds like its close to what you want.

Eric
 
M

Mark Space

EricF said:
AspectJ will not address those issues. It's best for cross-cutting concerns,
code that might be common across methods - logging, timing, and transactions
are frequent examples.

I've never worked with any type of aspect oriented programming, although
I've seen it described. At first blush I would have thought that it
might address the OP's needs.

So, when you wave code, are you weaving static methods? Or does the
code you weave in have access to a "this" pointer?

Because if "this" is accessible that could allow some pretty substantial
and useful stuff. If it's just static methods, then I guess it would be
pretty limited.
 
M

Mark Space

Kenneth said:
Not all of us would agree with this statement. I don't see it as a good
thing. I honestly don't see how you can justify that statement at all.

I agree with Lew. Verbosity is good in most case. My old eyes can
easily miss subtle changes in punctuation which drastically alter semantics.

Use big words please, so I can see the darn things.

I'm sure not every agrees, and I don't believe mine is the only
argument, just explaining my side of the story, is all.
 
J

jhc0033

This is a good thing. Why do some people speak as if it were not?

In my experience, some programmers just don't see the repetitiveness
and they think of all their typing as "productivity", "hard work" and
"not being lazy".

Recognizing the repetitiveness takes experience, exposure to a wide
variety of programming ideas, particular pattern recognition skills,
and perhaps some higher-order "mathematical" thinking. I know it
didn't come to me the moment I learned my first programming language.

I think very few programmers would actually claim that repetitiveness
is good. They probably see programming as an activity very differently
from me. I see it as *automating* things.

You say that you like all the verbosity because it makes things
explicit. Would you rather read/debug/maintain this mess (imagine it
in real code):

To destroy class a, destroy all of its fields
To clone class a, clone all of its fields
To default_construct class a, default_construct all of its fields
To write class a, write all of its fields
To read class a, read all of its fields
To close class a, close all of its fields
To destroy class b, destroy all of its fields
To clone class b, clone all of its fields
To default_construct class b, default_construct all of its fields
To write class b, write all of its fields
To read class b, read all of its fields
To close class b, close all of its fields
To destroy class c, destroy all of its fields
To clone class c, clone all of its fields
To default_construct class c, default_construct all of its fields
To write class c, write all of its fields
To read class c, read all of its fields
To close class c, close all of its fields
To destroy class d, destroy all of its fields
To clone class d, clone all of its fields
To default_construct class d, default_construct all of its fields
To write class d, write all of its fields
To read class d, read all of its fields
To close class d, close all of its fields
To destroy sequence doublyLinkedList, destroy all of its elements
To clone sequence doublyLinkedList, clone all of its elements
To write sequence doublyLinkedList, write all of its elements
To read sequence doublyLinkedList, read all of its elements
To close sequence doublyLinkedList, close all of its elements
To destroy sequence myVector, destroy all of its elements
To clone sequence myVector, clone all of its elements
To write sequence myVector, write all of its elements
To read sequence myVector, read all of its elements
To close sequence myVector, close all of its elements

(I had to write a few lines in Prolog to generate the above)

.... or just understand a few simple and machine-verified rules that
define it? If you had to change/add some policies, would you rather
change the rules (add a rule) or modify a huge number of classes in
your project?

I guess the answer depends on whether you are being paid per LOC.


People more eloquent than me wrote on this topic:
http://www.paulgraham.com/power.html

I'm just trying to understand whether Java would be palatable enough
for me to warrant further investment. GWT looks sweet.
 
A

Arne Vajhøj

In my experience, some programmers just don't see the repetitiveness
and they think of all their typing as "productivity", "hard work" and
"not being lazy".

Recognizing the repetitiveness takes experience, exposure to a wide
variety of programming ideas, particular pattern recognition skills,
and perhaps some higher-order "mathematical" thinking. I know it
didn't come to me the moment I learned my first programming language.

I think very few programmers would actually claim that repetitiveness
is good. They probably see programming as an activity very differently
from me. I see it as *automating* things.

You missed the point.

Verbose does not mean repetitive.

Arne
 
E

EricF

I've never worked with any type of aspect oriented programming, although
I've seen it described. At first blush I would have thought that it
might address the OP's needs.

So, when you wave code, are you weaving static methods? Or does the
code you weave in have access to a "this" pointer?

Because if "this" is accessible that could allow some pretty substantial
and useful stuff. If it's just static methods, then I guess it would be
pretty limited.

I've only touched AspectJ a bit, some code I inherited at work. Basically a
regular expression is used to insert bytecode - that's the weaving. You're not
weaving in methods, you're weaving in lines of code. You do have access to
"this".

The code was used to audit a number of "activities" in an existing code base.

I know Spring and JBoss use Aspects. They certainly have their uses. I hope
someone with more Aspect experience replies to the thread.

Eric
 
E

EricF

This is a good thing. Why do some people speak as if it were not?
I don't think I did.

When you just need to write a quick and dirty utility/script, Java's verbosity
is not an advantage. Groovy is pretty nice for such things. For larger tasks,
I like Java a lot.

Eric
 
M

Mark Space

EricF said:
I've only touched AspectJ a bit, some code I inherited at work. Basically a
regular expression is used to insert bytecode - that's the weaving. You're not
weaving in methods, you're weaving in lines of code. You do have access to
"this".

The weaving I saw -- possibly Spring, since that's one framework I
looked at a long while ago -- wove directly in byte code. In other
words, directly on the .class file, not in source code. (Early versions
of Aspect Oriented Programming I think used source code instead of byte
code.)

I thought it used annotations instead of the "regular expression" bit,
but I could be mistaken.

Anyway, with access to a this pointer, it seems like code weaving could
solve at least some of the OP's issues. I think it would work for
toString(), it might work for Clonable. Add a weave for Copyable and
DeepCopyable and you might have it, which weave into a clone() method,
and you might have it.

Java gets really close to full support for most of the OP's concerns.
Its toString() works fine, just not how the OP wanted. clone() and
serialization (with XML) are there, they just need a bit of tweaking.

I don't see the need, but if you really must drive a code base to the
minimum number of lines, and also support a lot of wordy, tedious
interfaces on every object, code weaving might get you there.

OTOH code weaving and GWT might throw the hell up. Weaving on byte codes
at least I'm sure would not be supported when your "byte codes" are
Javascript. Source code weaving... might work.
 
A

Arne Vajhøj

Kenneth said:
Not all of us would agree with this statement. I don't see it as a good
thing. I honestly don't see how you can justify that statement at all.

I think most would.

verbose = easy to read = easy to maintain = not expensive to maintain

Arne
 
A

Arne Vajhøj

EricF said:
I don't think I did.

When you just need to write a quick and dirty utility/script, Java's verbosity
is not an advantage. Groovy is pretty nice for such things.

True.

But it is the maintenance of huge projects that is the real
challenge.

But I agree that Java is not the best language for that type
of quick and dirty scripts.

Arne
 
A

Arne Vajhøj

Mark said:
I've never worked with any type of aspect oriented programming, although
I've seen it described. At first blush I would have thought that it
might address the OP's needs.

So, when you wave code, are you weaving static methods? Or does the
code you weave in have access to a "this" pointer?

Because if "this" is accessible that could allow some pretty substantial
and useful stuff. If it's just static methods, then I guess it would be
pretty limited.

I just read a bit about AspectJ and introductions.

Yes - AspectJ can add this kind of functionality.

Example:

package test;

public interface AutoToString {
String toString();
}

and

package test;

import java.lang.reflect.*;

public aspect AutoToStringImpl {
declare parents: test.* implements AutoToString;
public String AutoToString.toString() {
try {
StringBuilder sb = new StringBuilder();
Method[] m = getClass().getMethods();
for(int i = 0; i < m.length; i++) {
if(m.getName().startsWith("get") &&
m.getDeclaringClass() == getClass()) {
if(i > 0) {
sb.append(",");
}
sb.append(m.invoke(this, new Object[0]));
}
}
return sb.toString();
} catch(IllegalAccessException e) {
return "Ooops";
} catch(InvocationTargetException e) {
return "Ooops";
}
}
}

Arne

PS: No - I don't think many will want to use this code.
 
O

Owen Jacobson

Futhermore, Java really isn't all that verbose.  For Pete's sake, you can
acquire an entire monitor and synchronize threads with one keyword, ooh, big
overhead.

While I fundamentally agree with you, Lew, there *are* places where
Java is painfully verbose. The amount of typing required for closures
- anonymous classes - is ridiculous compared to other languages. And,
while there are certainly lots of ways to hurt yourself with closures,
there are many times when they're useful, too: just look at Spring's
FooCallback (HibernateCallback, JdbcCallback, etc) interfaces and
consider how much cleaner they'd be to use with a shorter syntax.

There are proposals in the works to streamline this aspect of Java;
"concise instance creation expressions" introduces the smallest
semantic changes (no new language constructs, only new syntax), and
there is also a proposal for full-blown closures and lambda
expressions from Bloch and others. We'll see what falls out.

-o
 
O

Owen Jacobson

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
 
M

Mark Space

Mark said:
I thought it used annotations instead of the "regular expression" bit,
but I could be mistaken.

Yup, here we go:

package testaj;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class Test {

@After("execution (* sayHello())")
public void sayAgain(){
System.out.println("again\n");
}

}

I do find the annotations to be a bit easier to read.

<http://www.jroller.com/ramlog/entry/using_the_aspectj_plug_in1>

For NetBeans 6.0, no less!
 
S

Stefan Ram

Eric Sosman said:
class got the program source in its original form, and half
got the same source but with all the comments removed. The
latter group found more of the bugs and found them faster ...

First case:

/* This method is intended to return the sum of its two arguments. */
int sum( final int augend, final int addend ){ return augend - addend; }

Second case:

int f( final int x, final int x1 ){ return x - x1; }

Here, one can not find the bug in the second case.

In the first case, one can not be sure, whether the bug is in
the code or in the documentation (possibly, the method now
should return the difference, and the documentation is wrong).
But at least one can spot that there is a contradiction.

(I deem identifiers to be documentation too when they
contain any information that would be lost by renaming
them to x, x1, x2, ... and so on.)
 
A

Arved Sandstrom

Eric Sosman said:
Lew said:
Kenneth said:
On Sun, 20 Apr 2008 09:54:19 -0400, Lew wrote:

EricF wrote:
Java is a bit verbose.
This is a good thing. Why do some people speak as if it were not?

Not all of us would agree with this statement. I don't see it as a good
thing. I honestly don't see how you can justify that statement at all.

Documentation of code is a good thing, yes? [...]

An experiment described in "The Psychology of Computer
Programming" (I think; it was a long time ago) cast doubt on
this axiom. A class of computer science students was handed
a quiz that required them to study the source of an existing
but buggy program, and to find and fix the bugs. Half the
class got the program source in its original form, and half
got the same source but with all the comments removed. The
latter group found more of the bugs and found them faster ...

I can see this happening, sure. The class of defects that can be identified
without knowing anything about the purpose of the code is sizeable -
uninitialized pointers, dangling pointers, off-by-one errors, total anarchy
when it comes to passing around pointers/references to variables, poor or no
memory management, ill-advised type conversion, no validation of inputs,
lack of thread safety etc etc. One can expect the number of defects of this
type to be substantially greater than syntactically correct code which fails
to accomplish what a comment says it should do. Faced with comments, I can
understand how a group of students might fixate on the logic/semantics, and
not spend so much time on the basic bugs.

I think this would be more of an observation about relatively inexperienced
code reviewers rather than any reason to rethink the usefulness of code
comments, though. After all, the comments are there to tell you what the
code does.

AHS
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,772
Messages
2,569,593
Members
45,105
Latest member
sheetaldubay7750ync
Top