views:

582

answers:

7

Java Reflection provides a mechanism to introspect an Object at runtime. No second thoughts, this is a great feature, but it breaks all the Refactoring conventions!

There is no easy way (other than File Search) even in modern IDE's to know which attribute is referenced and where. This makes Refactorings much more complex (tiresome!) and error prone.

To be frank, it's not just the Reflection API; Hibernate mapping files (hbm.xml) and JSP files both refer to the attributes as String and when you refactor your attribute name, then you have to manually change in all these places.

Worse, the changes in Hibernate mapping files or JSP files result in runtime errors.

I am interested in knowing how other programmers handle this in Java. Are there some tools? I use Eclipse/IBM RAD as main development platform. Normally we use a constant to define the attribute and use it whenever possible but its not always possible.

I would also be interested how other languages handle this!

+6  A: 

Java reflection causes many of the same problems you get with dynamically typed languages such as Python and Ruby. In fact, one way to think about dynamically typed languages is that everything is called using reflection, and the languages just provide a nice, clean syntax for reflection.

And yes, with dynamically typed languages (or heavy uses of reflection), refactoring is hard. You don't get the nice Eclipse refactoring capabilities. Instead, grep becomes your friend.

From my experience, the best thing you can do is build yourself a good safety net of unit tests. That way, if you break some dynamic code during refactoring, at least you'll catch it quickly when you run the tests.

If you're doing lots of statically typed code, you're in big trouble if you don't have a good base of unit tests. If you're doing lots of dynamically typed code (including code with lots of reflection), you don't have any hope of being successful without a good base of unit tests.

Clint Miller
Actually, the first IDE that implemented refactoring was Smalltalk, which is quite dynamic. AFAIK the refactoring tool did the analysis by monitoring the code as it ran (usually through unit tests) and seeing which paths are used, which methods are called, etc. It's possible to refactor dynamic code, but it is hard to implement and I believe that is the reason it isn't widely available in IDE's.
gooli
+1  A: 

Modern IDE's have the feature that when renaming a class, they will search for the fully qualified name in, for example, your xml files to try and rename any references you might have in those. Don't think it solves the problem - very often you don't absolutely reference class names.

Also, that is why particular care and consideration must be exercised before you use it in your own code.

But this problem with reflection is why using annotations is becoming more popular. The problem is reduced when using annotations.

But let me say, as the previous post rightly points out, if you don't have a good safety net of unit tests, any kind of refactoring, whether you use a lot of reflection or not, is dangerous.

Michael Wiles
How does annotation solve the problem in such scenarios? Can you give an example? Thx.
lud0h
It's in terms of persistence for example. If I use annotations to specify that a class is persistent, for example, and I rename that class, the annotation will stay and it will still be persistent. I will not have to go and find all the instances where the class is references in the mapping files and change that as well.
Michael Wiles
A: 

You might be interested in using IntelliJ IDEA, which will also search for refactored class names in comments and string constants.

Alex Feinman
netbeans (and problably others) too
dfa
Eclipse (and presumably netbeans) can do that too - but it's still not guaranteed to work, since it will only catch fully qualified class names
Michael Borgwardt
A: 

Well, it's another opportunity for IDE makes to sell expensive premium versions which will recognize and refactor class names used in specific configuration files.

Alternatively, such recurring cases can be handled by a test suite that performs sanity checking on such files, i.e. checks that all referred classes and methods exist. Such are specific to one file format, but are often relatively easy to write and can then be used to check all files of that format.

But there is no general solution for the direct, "manual" use of the reflection API - which is why it's generally discouraged.

Michael Borgwardt
The problem is not just with the Reflection API. The config files like in Hibernate or JSP are compile time bound and the tools doesn't capture them effectively.
lud0h
Since those files have a well-defined syntax, it is at least possible (and not too difficult).
Michael Borgwardt
A: 

Refactoring could be improved by introducing more "literals" in the language. E.g. imho .class literal are a great way to ensure compile-time safety of certain models. However the important thing to say here is that, sometimes, I want to lose compile-time safety. Strings are the most simple yet powerful way to express a loosely coupled contract between two layers since you can manipulate or match them against a regular expression, etc

The real problem of reflection is the verbose use of the API. The is the major cost for flexibility.

PS

Project coin could introduce somewhere in the future some new language construct to enhance this area.

dfa
A: 

As an aside, Reflection also causes issues if you want to protect your code via obfuscation. Typical obfuscation tools now require you to maintain a list of all files that you do not want obfuscated so that reflection from all the XML config files works properly.

That said, A J2EE version of Eclipse IDE along with suitable plugins for the major frameworks like Hibernate, Spring etc will do a fairly good job of handling refactoring. Unit tests will reduce the testing cycle, but the concern is that sometimes the unit tests also depend on some XML configuration forcing you to use reflection. So it is possible to break unit tests along with your code while refactoring.

Thimmayya
A: 

What about taggin classes, methods, fields you know are accessed by reflection? The IDE could warn you when you change their names.

Farr