1

I'm involved in a project with several modules. I found that programmers have designed one module to be easily decoupled from its dependent modules using Java Reflection. If other modules need to call a method in this module, the programmers are expecting them to use reflection to call it. This has resulted in a lot of places with hard-coded reflection calls. By hard-coded, I mean the class and method names are permanently fixed as Strings, which kind of defeats the purpose of reflection which is supposed to be for dynamic programming.

How can this be justified? I feel they are being novice about it and misusing the reflection API. I think polymorphism is the right way to decouple a module from another without breaking functionality. (Unfortunately, changing the entire code base to polymorphism is way too much maintenance.)

0

4 Answers 4

6

If the sole purpose of the use of reflection is to decouple modules (in an abstract sense), then (IMO) it cannot be justified.

Why?

Because in reality it is NOT decoupling them. Rather it is replacing one form of coupling with another form. What is more, the second form of coupling (i.e. the hard-wired class and method name strings) is harder to spot, and more susceptible to breakage.


OTOH, if the use of reflection is intended to achieve other things, then it may well be justifiable on that basis. For instance, the examples in the other Answers all have more specific purpose than just "reducing coupling".

1
  • In the scope of the question, reflection is only used for decoupling. The developers themselves claimed that they are using reflection as a solution - so that in some projects, they can avoid including the reflected module without having to remove references to it (since references are in strings, compiler will not complain that they are missing)... yea, a stupid way to do things, but oh well..
    – ADTC
    Commented Sep 25, 2013 at 8:19
5

Yes, unless reflection uses some names not available at compile time, it usually should be replaced by factories or dependency injection.

OTOH there are rare cases when exact class names are known at compile time, but classes named so are not available at build time. A classic example is JDBC, which used to use the Class.forName("com.vendor...") paradigm. The name of the JDBC driver(s) class is known at compile time, but a .jar with the specified class, or often several for several supported DBMSes, is not available.

This case is still rather special: not only it assumes that classes referenced by reflection are deployed in separate jars, it assumes that some of such classes may not be available at all. This is a reasonable assumption for a publicly-used library; I don't know if it's reasonable in your case.

Anyway, modern containers don't require client code to use reflection, they use dependency injection to provide specific replaceable implementations of e.g. JDBC drivers.

I think you should consider using a dependency-injection framework in your case. The DI framework might use reflection internally, but at least all such reflection would be concentrated in a thin well-defined layer.

1

a better way is to use interfaces and some method to locate the implementing classes

the interfaces preempt the need for reflection in the calling code, this is doable during a refactor, just extract the interfaces (and data objects) and put them where the client code can reference it and replace all reflection with a call to the interface

there are several ways of finding the implementing classes: one of them is used by the ImageIO service system, it involves a file in the META-INF folder of the jar containing the implementing module and including the jar in the classpath

0

Reflection for decoupling is always a bad idea. Interfaces are the way to go. You can dynamically detect implementations using SPI and/or OSGi or similar. Use a factory to hide the lookup details.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.