57

I don't know why, but I always feel like I am "cheating" when I use reflection - maybe it is because of the performance hit I know I am taking.

Part of me says, if it is part of the language you are using and it can accomplish what you are trying to do, then why not use it. The other part of me says, there has to be a way I can do this without using reflection. I guess maybe it depends on the situation.

What are the potential issues I need to look out for when using reflection and how concerned should I be about them? How much effort is it worth spending to try to find a more conventional solution?

5
  • 2
    I guess it depends on the language and the environment. Some support it, even encourage it. Sometimes when working in Java I have wished for better reflection support. Aug 15, 2011 at 14:16
  • 19
    Well, I guess it's not so hard to dinstguish between "cheating reflection" and a valid use of it: When you inspect private members or use it to call private methods (to work around interfaces), then it's very likely cheating. When you use it to interact with types you have otherwise no knowledge about, then it's probably ok (databinding, proxies etc.).
    – Falcon
    Aug 15, 2011 at 15:05
  • 1
    What language are you using? Brainfuck does not have reflection and Python is just different.
    – Job
    Aug 15, 2011 at 17:08
  • 1
    I also never understood why it is allowed to access private methods through reflection. According to my intuition it should be forbidden.
    – Giorgio
    Aug 15, 2011 at 21:06
  • One of the very few times reflection is useful is when you are trying to inject dependencies into a class under test, and that class is not dependency-injection friendly. Though that's a workaround for when you don't have the authority to refactor the class under test. Sometimes you have to cheat because existing code doesn't follow good practices :) Aug 7, 2019 at 17:49

14 Answers 14

52

No, it's not cheating - it is a way to solve problems in some programming languages.

Now, it is often not the best (cleanest, simplest, easiest to maintain) solution. If there is a better way, use that one indeed. However, sometimes there isn't. Or if there is, it is just so much more complex, involving a lot of code duplication etc. which makes it infeasible (difficult to maintain in the long run).

Two examples from our current project (Java):

  • some of our testing tools use reflection to load configuration from XML files. The class to be initialized has specific fields, and the config loader uses reflection to match the XML element named fieldX to the appropriate field in the class, and to initialize the latter. In some cases, it can build a simple GUI dialog box out of the identified properties on the fly. Without reflection, this would take hundreds of lines of code across several applications. So reflection helped us put together a simple tool quickly, without much fuss, and enabled us to focus on the important part (regression testing our web app, analysing server logs, etc.) rather than the irrelevant.
  • one module of our legacy web app was meant to export/import data from DB tables to Excel sheets and back. It contained a lot of duplicated code, where of course the duplications were not exactly the same, some of them contained bugs etc. Using reflection, introspection and annotations, I managed to eliminate most of the duplication, cutting down the amount of code from over 5K to below 2.4K, while making the code more robust and way easier to maintain or extend. Now that module ceased to be a problem to us - thanks to the judicious use of reflection.

The bottom line is, like any powerful tool, reflection too can be used to shoot yourself in the foot. If you learn when and how (not) to use it, it can bring you elegant and clean solutions to otherwise difficult problems. If you abuse it, you can turn an otherwise simple problem into a complex and ugly mess.

7
  • 8
    +1 Reflection is incredibly useful for data import/export when you have intermediate objects for conversion reasons.
    – Ed James
    Aug 15, 2011 at 14:34
  • 2
    It's also incredibly useful in data-driven apps - instead of using a massive stack of if (propName = n) setN(propValue);, you can name your (i.e.) XML tags the same as your code properties and run a loop over them. This method also makes it far simpler to add properties later.
    – Michael K
    Aug 15, 2011 at 15:54
  • Reflection is used heavily in Fluent interfaces, like FluentNHibernate. Aug 15, 2011 at 19:13
  • 4
    @Michael: Until you decide to rename one of those properties in the class and find that your code explodes. If you don't need to maintain comparability with things your program generates, that's fine, but I suspect that's not most of us. Aug 15, 2011 at 19:44
  • 1
    @Billy, I didn't mean to contradict you, I agree with what you wrote. Although, the example you bring is IMHO more a subcase of the general rule "avoid changing public interfaces". Aug 16, 2011 at 6:42
41

It's not cheating. But it is usually a bad idea in production code for at least the following reasons:

  • You lose compile-time type safety - it's helpful to have the compiler verify that a method is available at compile time. If you are using reflection, you'll get an error at runtime which might affect end users if you don't test well enough. Even if you do catch the error, it will be be more difficult to debug.
  • It causes bugs when refactoring - if you are accessing a member based on its name (e.g. using a hard-coded string) then this won't get changed by most code refactoring tools and you'll instantly have a bug, which might be quite hard to track down.
  • Performance is slower - reflection at runtime is going to be slower than statically compiled method calls/variable lookups. If you're only doing reflection occasionally then it won't matter, but this can become a performance bottleneck in cases where you are making calls via reflection thousands or millions of times per second. I once got a 10x speedup in some Clojure code simply by eliminating all reflection, so yes, this is a real issue.

I'd suggest limiting the use of reflection to the following cases:

  • For quick prototyping or "throwaway" code when it is the simplest solution
  • For genuine reflection use cases, e.g. IDE tooling that allows a user to examine the fields/methods of an arbitrary object at runtime.

In all other cases I'd suggest figuring out an approach that avoids reflection. Defining an interface with the appropriate method(s) and implementing it on the set of classes you want to call the method(s) on is usually sufficient to solve most simple cases.

7
  • 3
    +1 -- there are several use cases for reflection; but most of the time I see programmers using it they are papering over designs with serious flaws. Define interfaces and attempt to remove dependency on reflection. Just like GOTO, it has its uses, but most of them aren't good. (Some of them are good, of course) Aug 15, 2011 at 19:43
  • 3
    Bear in mind that the above points may or may not apply to your favourite language. For instance, reflection has no speed penalty in Smalltalk, nor do you lose compile-time safety, because computation is entirely late bound. Aug 15, 2011 at 19:47
  • Reflection in D don't has drawback you mention. So I would argue that you re blaming implementation in some languages more tha refelection itself. I don't know much about smalltalk, but according to @Frank Shearar, it doesn't have thoses drawback too.
    – deadalnix
    Aug 15, 2011 at 20:32
  • 2
    @deadalinx: To which downside do you refer? There are several in this answer. The performance issue is the only thing that's language dependant. Aug 15, 2011 at 20:38
  • 1
    I should add that the second issue - bugs caused during refactoring - is probably the most serious. In particular, relying on something having a particular name breaks instantly when that thing's name changes. The errors thus caused may be less than informative, unless you're very careful. Aug 16, 2011 at 8:06
11

Reflection is just another form of meta-programming, and just as valid, as the type-based parameters that you see in most languages these days. Reflection is powerful and generic, and reflective programs are a high order of maintainability (when used correctly, of course) and more so than purely object-orientated or procedural programs. Yes, you pay a performance price- but I'd gladly go for a slower program that's more maintainable in many, or even most, cases.

4
  • 2
    +1, this helps me understand what reflection is. I'm a C++ programmer, and so I've never really grokked reflection. This helps. (Though I confess that from my perspective, Reflection seems like an attempt at reconciling a deficiency in the language. We C++ guys use templates for that. So I suppose you could say the same of that. :)
    – greyfade
    Aug 15, 2011 at 16:42
  • 4
    Re performance - in some cases, you can use the reflection API to write back fully performance code. For example, in .NET you can write IL into the current app - hence your "reflection" code can be just as fast as any other code (except you can remove a lot of the if/else/whatever, as you've already figured out the exact rules) Aug 15, 2011 at 18:42
  • @greyfade: In a sense, templates are doing compile-time-only reflection. Being able to do it at runtime has the advantage of allowing powerful capabilities to be constructed in the application without having to recompile. You trade performance for flexibility, an acceptable tradeoff more of the time than you might expect (given your C++ background). Aug 16, 2011 at 10:18
  • 1
    I don't understand your answer. You seem to be saying that programs that use reflection are more maintainable than those that don't, as if reflection is a superior programming model that should supplant object-oriented and procedural programs if performance is not needed.
    – DavidS
    Feb 24, 2015 at 22:26
8

Reflection is an awesome tool if you are a library author, and thus have no influence over the incoming data. A combination of reflection and meta-programming can allow your library to work seamlessly with arbitrary callers, without them having to jump through hoops of code-generation etc.

I do try to discourage from reflection in application code, though; at the app layer you should be using different metaphors - interfaces, abstraction, encapsulation etc.

3
  • Such libraries are often hard to use and best avoided (e.g. Spring). Aug 7, 2019 at 17:35
  • 1
    @Sridhar so you've never used any serialization API? Or any ORM/micro-ORM? Aug 7, 2019 at 17:40
  • I've used them through no choice of my own. It's been demoralizing running into problems I could have avoided if I wasn't being told what to do. Aug 7, 2019 at 17:41
8

Surely it all depends on what are you trying to achieve.

For example, I wrote a media checker application that uses dependency injection to determine what sort of media (MP3 files or JPEG files) to check. The shell needed to display a grid containing the pertinent information for each type, but it had no knowledge of what it was going to display. This is defined in the assembly that reads that type of media.

Therefore I had to use reflection to get the number of columns to display and their types and names so I could set the grid up correctly. It also meant that I could update the injected library (or create a new one) without changing any other code or configuration file.

The only other way would have been to have a configuration file that would need to be updated when I switched the type of media being checked. This would have introduced another point of failure for the application.

1
  • 1
    "Surely it all depends on what are you trying to achieve." +1
    – DaveShaw
    Aug 15, 2011 at 19:26
7

Reflection is fantastic for building tools for developers.

As it allows your build environment to inspect the code and potentially generate the correct tools to manipulate/init inspect the code.

As a general programming technique it can be useful but is more brittle than most people imagine.

One really development use for reflection (IMO) is that it makes writing a generic streaming library very simple (as long as your class description never changes (then it becomes a very brittle solution)).

1
  • Indeed, Spring is "more brittle than most people imagine." Aug 7, 2019 at 17:36
5

Use of reflection is often harmful in OO languages if not used with great awareness.

I have lost count of how many bad questions I have seen on StackExchange sites where

  1. The language in use is OO
  2. The author wants to find out which type of object has been passed in and then call one of its methods
  3. The author refuses to accept that reflection is the wrong technique and accuses anybody who points this out as "not knowing how to help me"

Here are typical examples.

Most of the point of OO is that

  1. You group functions which know how to manipulate a structure/concept with the thing itself.
  2. In any point of your code you should know enough about an object's type to know what relevant functions it has and ask it to call its particular version of those functions.
  3. You ensure the truth of the previous point by specifying the correct input type for every function and having each function know no more (and do no more) than is relevant.

If at any point in your code, point 2 is not valid for an object you have been passed then one or more of these is true

  1. The wrong input is being fed in
  2. Your code is poorly structured
  3. You have no idea what the hell you are doing.

Poorly skilled developers simply do not get this and believe that they can be passed anything in any part of their code and do what they want from a (hard-coded) set of possibilities. These idiots use reflection a lot.

For OO languages, reflection should only be needed in meta activity (class loaders, dependency injection etc). In those contexts, reflection is needed because you are providing a generic service to assist the manipulation/configuration of code which you know nothing about for a good and legitimate reason. In almost any other situation, if you are reaching for reflection then you are doing something wrong and you need to ask yourself why this piece of code does not know enough about the object that has been passed to it.

3

An alternative, in cases where the domain of the reflected classes is well-defined, is to use reflection along with other metadata to generate code, instead of using reflection at runtime. I do this using FreeMarker/FMPP; there are lots of other tools to choose from. The advantage to this is that you end up with "real" code that can easily be debugged, etc.

Depending on the situation, this can help you make a lot faster code - or just a lot of code bloat. It avoids the disadvantages of reflection:

  • loss of compile-time type safety
  • bugs due to refactoring
  • slower performance

mentioned earlier.

If reflection feels like cheating, it may be because you're basing it on a lot of guesswork that you're not sure of, and your gut is warning you that this is risky. Be sure to provide a way to enhance the metadata inherent in reflection with your own metadata, where you can describe all the quirks and special cases of the real-world classes you may encounter.

2

It isn't cheating, but like any tool, it should be used for what it is intended to solve. Reflection, by definition, allows you to inspect and modify code through code; if that is what you need to do, then reflection is the tool for the job. Reflection is all about meta-code: Code that targets code (as opposed to regular code, which targets data).

An example of good reflection use is generic web service interface classes: A typical design is to separate protocol implementation from payload functionality. So then you have one class (let's call it T) that implements your payload, and another that implements the protocol (P). T is fairly straightforward: for every call you want to make, simply write one method that does whatever it is supposed to do. P, however, needs to map web service calls to method calls. Making this mapping generic is desirable, because it avoids redundancy, and makes P highly reusable. Reflection provides the means to inspect class T at runtime and call its methods based on strings passed into P through the web service protocol, without any compile-time knowledge of class T. Using the 'code about code' rule, one can argue that class P has the code in class T as part of its data.

However.

Reflection also gives you tools to get around restrictions of the language's type system - theoretically, you could pass all parameters as type object, and call their methods through reflections. Voilà, the language that is supposed to enforce strong static typing discipline now behaves like a dynamically typed language with late binding, only that the syntax is far more elaborate. Every single instance of such a pattern I've seen so far has been a dirty hack, and invariably, a solution within the language's type system would have been possible, and it would have been safer, more elegant, and more efficient in all regards.

A few exceptions exist, such as GUI controls that can be data-bound to various non-related types of data sources; mandating that your data implement a certain interface just so you can data-bind it isn't realistic, and neither is having the programmer implement an adaptor for each type of data source. In this case, using reflection to detect the type of data source and adjusting the data binding is a more useful choice.

2

One problem we have had with Reflection is when we added Obfuscation to the mix. All classes get new names and suddenly loading a class or function by its name stops working.

1

It totally depends. An example of something that would be hard to do without reflection would be to replicate ObjectListView. It also generates IL code on the fly.

1

Reflection is the primary method of creating convention-based systems. I would not be surprised to find it is in use heavily inside most MVC frameworks. It's a major component in ORMs. Chances are, you're already using components built with it every day.

The alternative for such a use is configuration, which has its own set of drawbacks.

0

Reflection can achieve things that simply can't be done practically otherwise.

For example, consider how to optimize this code:

int PoorHash(char Operator, int seed, IEnumerable<int> values) {
    foreach (var v in values) {
        seed += 1;
        switch (char) {
            case '+': seed += v; break;
            case '^': seed ^= v; break;
            case '-': seed -= v; break;
            ...
        }
        seed *= 3;
    }
    return seed;
}

There's an expensive test smack in the middle of the inner loop, but extracting it requires rewriting the loop once for each operator. Reflection allows us to get performance on par with extracting that test, without repeating the loop a dozen times (and thereby sacrificing maintainability). Just generate and compile the loop you need on the fly.

I have actually done this optimization, although it was a bit more complicated of a situation, and the results were amazing. An order of magnitude improvement in performance and fewer lines of code.

(Note: I initially tried the equivalent of passing in a Func instead of a char, and it was slightly better, but not nearly the 10x reflection achieved.)

5
  • 1
    The better optimization is to pass a functor instead. Will likely get inlined at runtime by the JIT compiler and is more maintainable than reflection. Aug 15, 2011 at 20:47
  • That would be more maintainable, and I actually try it first, but it wasn't fast enough. The JIT was definitely not inlining it, probably because in my case there was a second inner loop over the operations to perform. Aug 16, 2011 at 16:24
  • Also, I point out that what you've got there is really self modifying code, which isn't really reflection. One accesses it through reflection APIs in most languages which do support reflection, but it can be done just as simply in languages not supporting reflection (e.g. it would be possible in C++) Aug 16, 2011 at 17:20
  • I wanted to avoid the standard 'structural equality' example. Reflection is not necessary for self-modifying code, but it certainly helps. Aug 18, 2011 at 16:48
  • Not really. You can do that in non-reflection languages just fine. Aug 18, 2011 at 17:23
-2

No way is it cheating... Rather, it empowers application servers to run the classes made by the user with the name of their choice, hence providing flexibility to the user, not cheating them.

And if you want to see the code of any .class file (in Java) then there are several decompilers available free of charge!

3
  • Decompilation isn't a reflection feature. Aug 15, 2011 at 20:49
  • yes, it is not... But i meant to say that if u feel like cheating while using reflection(which provide you details of any class in java) than u are wrong bcoz reflection is a very useful concept and if getting details of any class is what is concerning you than that can be done easily with any decompiler... Aug 16, 2011 at 16:23
  • 2
    Reflection is a useful concept in some cases, yes. But 99.9% of the time I see it being used I see it used to hack around a design error. Aug 16, 2011 at 17:17

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