Lukasz has posted 3 posts at DZone. You can read more from them at their website. View Full User Profile

Avoid Reflection

05.14.2010
| 9677 views |
  • submit to reddit

The Java Reflection API is a very nice feature of the Java language. With the API you can do the magic with Java classes, create an object or call a method on the fly based only on a name. The real Magic!

So then, we all should use it all the time, to write a better code, yes? NO!

Avoid using it, try to write a code without the Reflection. The worst you can do is if you introduce some generic mechanism with it - a custom validation framework or a flow engine where class and method names are stored as a String (in a text file or a XML file).

You can ask: why?

The answer is simple: your IDE doesn't support it! When you refactor your class or method, eg. just rename it, IDE will find all the references and change them appropriately for you. But IDE won't know about your custom solution, is just a text, nothing more!

When you are using the Reflection, your IDE is blind!

Right now I'm working on our custom validation framework, to move definitions of validation from a XML file directly to a Java code. The case is, to not to change the validators, just used them as is. And not to use the Reflection as well ;-)

I've done some draft implementation base on anonymous classes and the word "final" (thanks Rafal for the tip!). And introduce the ValidationAware interface to be able at the same time use the old way and my new solution! Next week on Monday I will ask other team mates for opinion!

References
Published at DZone with permission of its author, Lukasz Lenart. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Gabriel Axel replied on Fri, 2010/05/14 - 5:59am

I think a better recommendation would be to stick to static typing as opposed to using strings, and not to avoid using the Reflection API entirely. When used with annotations, the argument you presented is not relevant, and in fact Reflection is the only way to work with annotation at runtime. Also the way Guice uses Reflection to instantiate classes and inject instances (which may or may not use annotations) is very clean and type-safe. Bottom line - reflection is not more dangerous than any other language feature, you just need to write good type-safe code.

Nathan Pruett replied on Fri, 2010/05/14 - 6:34am

It's much more important to know when to use reflection and when not to than to simply say not to use it at all.  I'm also not sure what IDE you're using, but both Eclipse and IDEA are "smart enough" to search for class name usages in text files.

Jacek Furmankiewicz replied on Fri, 2010/05/14 - 7:23am

Uhm...have you heard of unit testing?

That's what you use to ensure the dynamic parts of your app don't break over time. Just like they do in dynamic languages like Python or Ruby.

I use reflection a lot in my library and it's great. Do not avoid reflection, but learn it and use it when appropriate (and performance is not an issue).

Sam Lewis replied on Fri, 2010/05/14 - 7:36am

Making a blanket statement like 'Avoid Reflection' is not very useful, implementing a framework like Spring / Dozer etc without reflection would be a challenge.

That is like me saying avoid writing a custom validation framework especially one where the rules are defined in xml.

Scott Hickey replied on Fri, 2010/05/14 - 9:38am

Reflection is incredibly powerful and can make your code more maintainable not less.

Assume the same set of properties on an object that might get used in, say, 10 places throughout a project and the set of properties changes over time. Now you need to process an additional properties on that object in the same way, so change code in 9 of the places and forget one. The IDE won't help you with this kind of error which happens all of the time in complex systems when someone has to update the system who doesnt know about all 10 places. Using reflection, the code doing work on this set of properties may get written once and never need to be touched again - a much better option over the long term.

What's disappointing is that this article reminds me how a large percent of Java developers can't use their programming language without an IDE.

 Memo to new Java devs: Java != Eclipse

 Libraries and language features that help support maintainability and readability should not be avoided. Programming craftsmanship extends beyond the IDE.

 

Slava Imeshev replied on Fri, 2010/05/14 - 2:09pm

I'd say that every tool has its own use. In that I don't agree with the Lukasz completely dimissing reflection. Sure it may complicate things if you use it blindly but it can also make things easier. All J2EE and servlet containers are built using reflection. They just wouldn't be possible without it.

Myself I rarely find need for relflection but when I do, I use it. Sure, unit tests are a must, reflection or else.

 Pick the right tool for the job and you will be fine.

 

Regards,

 Slava Imeshev

 

Stephane Vaucher replied on Sat, 2010/05/15 - 10:06am

I disagree completely. The author states: "So then, we all should use it all the time, to write a better code, yes? NO!" why? because the IDE does not support it? I guess the author does not have much experience if he believes that IDE support is more important than code quality. Between better tool-support and better code, always go for better code. Of course reflection is useful only for certain problems, and can lead to performance problems, but these issues were not the ones discussed here.

Travis Calder replied on Sat, 2010/05/15 - 4:39pm

Strange, the IDE I use always seems to find text-occurences of class names just fine, and normally finds method names too.

Sometimes I have to do a bit of rooting if I have multiple classes with similar names, but that's ok. My test suite (unit -> functional -> acceptance) always catches those and warns me that I missed something.

If I may, one of the most powerful frameworks I've gotten my hands on lately is Camel, which makes heavy use of reflection. In fact, it has to. Camel's entire purpose in life is to define data-routes at startup, then have data automatically flow through them. The data-route is defined in a single place (either XML or a single "RouteBuilder" class) so that you have the option to knit together POJOs in any order you want, or even multiple orders if you have that desire.

The concept is extremely powerful, and is solely responsible for my team moving at least one if not two orders of magnitude faster than we would otherwise, while still being able to create extremely testable code.

Alessandro Santini replied on Sun, 2010/05/16 - 5:36am

Then I do not want to hear your position on byte-code manipulation and dynamic languages ...

There are so many technologies relying on reflection (annotations anyone?) that such a statement sounds like coming from the times of the doomsday fear...

What about unit testing? Shouldn't this highlight broken code in a consistent way? Mh... I guess JUnit is not in your toolbox...

I think you could use the time you spent to write this article in a more productive way. Nothing personal.

Artur Biesiadowski replied on Sun, 2010/05/16 - 9:01am

To people saying unit testing is silver bullet - in many cases, string-based configuration which is driving reflection will be part of runtime/deployment configuration, which is exactly the part which you are NOT unit testing. In some cases, entire point of such config is to allow unit testing simple config, not deployment config.

I don't think that reflection is evil on it's own - but in many cases, it is a lot less unit-testable than other aspects of the system.

Alessandro Santini replied on Sun, 2010/05/16 - 1:53pm in response to: Artur Biesiadowski

Sorry Artur, I really fail to get your point. If tests provide good coverage of the source code, there will surely be a point where the reflection code will be tested.

This is not about seeing unit testing as a silver bullet, it is instead about seeing test as necessary and properly planned and executed.

Stefan Ruska replied on Sun, 2010/05/16 - 4:07pm

I would recommend you writing your own annotation processor. It can be seamlessy integrated with current IDEs and it can check structural properties of source code during compilation. What is even more you can specify code completion hints and therefore really pimp IDE's capabilities.

 IDEs are not blind they just have very dark sunglasses :)

Gervais Blaise replied on Mon, 2010/05/17 - 1:59am

I fully agree with Scott Hickey : "Reflection is incredibly powerful and can make your code more maintainable not less." The IDE is a very bad argument, he is helping us to write code but it will not write code for us. It is like saying "Don't use your hammer because it can't screwing"

Jacek Furmankiewicz replied on Mon, 2010/05/17 - 8:56am

I think it would be a good idea for the author to ask JL to remove this article. It's one of those "doh!" mistakes you don't want to have hanging around in one's online portfolio forever.

We all make mistakes. This article is one of those.

 

Slava Imeshev replied on Mon, 2010/05/17 - 1:27pm in response to: Jacek Furmankiewicz

Come on, everyone has a right to speak up. I don't think anything should be removed.

 

Regards,

Slava Imeshev

 

Artur Biesiadowski replied on Mon, 2010/05/17 - 3:09pm in response to: Alessandro Santini

@Alessandro

OP is complaining about having possible mistakes in text/xml files which will have hard-to-spot mistakes. Source code coverage won't help, because they are not source code. Often, they are configuration/deployment info, which differs between test and production environments - so from very definition, you won't be able to test production config.

Of course, situation is not very different from having any kind of configuration file - you can always make a type there, which will be present only in production and will slip through the testing. It is that reflection based frameworks like spring sometimes blur distinction between configuration of environment and configuration of program and you need to be extra careful here.

Alessandro Santini replied on Mon, 2010/05/17 - 5:15pm in response to: Artur Biesiadowski

I still don't agree Artur. If you test at a unit/component/solution level, you will exercise that configuration file sooner or later. If you do not need to test how your software components interact with their configuration files, it means that you do not need them.

Lukasz Lenart replied on Thu, 2010/05/27 - 5:12am

Thanks for all your comments. And your are right - unit testing isn't used widely in that project - especially for code base on the Refelection API. Also it's just an ordinary application and not a fancy superb library or a framework - just the application that will be used by ordinary users and not by other Java developers.

I agree - we need the Reflection API when we're writing libs like Spring or Guice or even Struts 1. But for an application in most cases is not needed. Or you must protect that code with unit tests.

Kind regards!

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.