Author Topic: [Java] Efficiency/best practice dilemna  (Read 5662 times)

0 Members and 1 Guest are viewing this topic.

Offline Chavo

  • x86
  • Hero Member
  • *****
  • Posts: 2219
  • no u
    • View Profile
    • Chavoland
[Java] Efficiency/best practice dilemna
« on: July 24, 2006, 12:03:47 pm »
The code in question is kinda in-between a couple versions I am playing around with, so I won't bother posting all of it since it won't help ;)

I have a class called EventManager which basically receives a generic Event, iterates through a list of EventHandlers for that specific Event and calls a dispath() method on each of those Handlers.

dispatch utilizes Reflection in order to call a method by name that wants to handle the raised Event.  Let me know if I've lost you yet ;)

All of the above works fine.  Now for the 'dilemna' (I wouldn't call it a problem, just a matter of deciding which solution is better).

A class that wants to handle a raised event can have any name it wants, but it must accept the type of arguments that dispatch() specifies.  Since there are a number of events, dispatch() calls the handling object's method and passes a generic superclass.  The handling method must then cast to a sub-class if they want to access the sub-class data.  I find this less than pretty and somewhat error prone.

The alternative is to write seperate dispatch() methods for every single Event type (there are a lot) so that the parent class does not have to be the argument.  This makes it safer/easier for the handling methods, but significantly sloppier looking with all the dispatch methods (and very redundant code).

There is a third option.  One dispatch method could be written accepting the parent class.  The dispatch method could then switch on the type of event and call the handling event with the proper child class.  The problem I see with this approach is that you are switching and casting multiple times for the same object because dispatch will be called multiple times for a single event if there are multiple handlers for that event.

Thoughts?  Am I being too vague?

Offline iago

  • Leader
  • Administrator
  • Hero Member
  • *****
  • Posts: 17914
  • Fnord.
    • View Profile
    • SkullSecurity
Re: [Java] Efficiency/best practice dilemna
« Reply #1 on: July 24, 2006, 01:54:32 pm »
You could define some standard form, for example:
dispatch(int code, String data);

Then, to accept the differences for other definitions, add an array of objects to the end:
dispatch(int code, String data, Object []vars);

That's like using a variable number of arguments in C, people can do:
dispatch(1, "hi", new Cattle(), null);
And the last two parameters will end up in the object array.  IIRC. 

That's Java's answer to printf() and other variable-parameter functions. 

Incidentally, this may not be the best answer, and I believe it's new in Java 1.5. 

Offline Chavo

  • x86
  • Hero Member
  • *****
  • Posts: 2219
  • no u
    • View Profile
    • Chavoland
Re: [Java] Efficiency/best practice dilemna
« Reply #2 on: July 24, 2006, 03:35:54 pm »
I don't see how that helps, or maybe I'm not completely getting it.  It looks very similar to the params functionality of C# which I am very familar with.

Maybe I should explain more about how I am using reflection.

This is my EventHandler class:
Code: [Select]
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;

import events.*;

public class EventHandler {

private Object obj;
private Method method;

public EventHandler(Object obj, String methodName)
{
this.obj = obj;
try{
method = obj.getClass().getMethod(methodName,new Class[] {ParentEvent.class});
} catch (Exception e) {
e.printStackTrace(System.out);
}
}

public void dispatch(BNetEvent event) {

try{
method.invoke(obj, new Object[] {event});
}catch(IllegalAccessException iae) {
iae.printStackTrace();
}
catch(InvocationTargetException ite) {
ite.printStackTrace();
}
}

public boolean equals(Object o)
{
try{
EventHandler compare = (EventHandler)o;
if(this.obj.getClass().getCanonicalName().equalsIgnoreCase(compare.obj.getClass().getCanonicalName())
&& this.method.getName().equalsIgnoreCase(compare.method.getName()))
return true;
}
catch(Exception e) {}

return false;
}
}

I create an instance of EventHandler for every event that I want to handle.  I pass the constructor a reference to the object and method name where I want to write the code to handle this event.  When dispatch is called, I use the Method.invoke() method (Method belongs to java.lang.reflection) to call the handling code with a generic object[] for arguments. The limitation on those arguments is in the actual Method constructor.

Offline Chavo

  • x86
  • Hero Member
  • *****
  • Posts: 2219
  • no u
    • View Profile
    • Chavoland
Re: [Java] Efficiency/best practice dilemna
« Reply #3 on: July 24, 2006, 05:20:13 pm »
gahh, DUH!

Quote
   public EventHandler(Object obj, String methodName, Class classType)
   {
      this.obj = obj;
      try{
         method = obj.getClass().getMethod(methodName,new Class[] {classType});
      } catch (Exception e) {
         e.printStackTrace(System.out);
      }
   }

determine the class to use in the constructor!  Now to add better error handling if someone trys to use the wrong class.  Superclasses will work without erros though I think, yay.
« Last Edit: July 24, 2006, 05:28:57 pm by unTactical »

Offline Joe

  • B&
  • Moderator
  • Hero Member
  • *****
  • Posts: 10319
  • In Soviet Russia, text read you!
    • View Profile
    • Github
Re: [Java] Efficiency/best practice dilemna
« Reply #4 on: July 25, 2006, 12:42:13 am »
Seriously, what is with iago and Cattle? :p
I'd personally do as Joe suggests

You might be right about that, Joe.


Offline iago

  • Leader
  • Administrator
  • Hero Member
  • *****
  • Posts: 17914
  • Fnord.
    • View Profile
    • SkullSecurity
Re: [Java] Efficiency/best practice dilemna
« Reply #5 on: July 25, 2006, 09:47:20 am »
Seriously, what is with iago and Cattle? :p
Long story

Offline MyndFyre

  • Boticulator Extraordinaire
  • x86
  • Hero Member
  • *****
  • Posts: 4540
  • The wait is over.
    • View Profile
    • JinxBot :: the evolution in boticulation
Re: [Java] Efficiency/best practice dilemna
« Reply #6 on: July 25, 2006, 12:17:32 pm »
If you don't mind my saying so, rather than using type reflection which is typically slow, it would probably be better to use an interface or series of interfaces.  I can't imagine that dynamic method invocation the way you have it designed is much different than the way .NET is:



You're using what looks to be the equivalent of MethodBase.Invoke. 

Of course, all of this could be handled with delegates, and still be type-safe, but since Java sucks...  :P
I have a programming folder, and I have nothing of value there

Running with Code has a new home!

Our species really annoys me.

Offline iago

  • Leader
  • Administrator
  • Hero Member
  • *****
  • Posts: 17914
  • Fnord.
    • View Profile
    • SkullSecurity
Re: [Java] Efficiency/best practice dilemna
« Reply #7 on: July 25, 2006, 01:13:21 pm »
Incidentally, on that graph, the call is probably .00001seconds, or less, which would make the invoke like .00001seconds, which is still nothing. 

When it comes to making a decision between programming and speed, choose programming.  With modern computers, a small speed difference rarely matters. 

Offline Chavo

  • x86
  • Hero Member
  • *****
  • Posts: 2219
  • no u
    • View Profile
    • Chavoland
Re: [Java] Efficiency/best practice dilemna
« Reply #8 on: July 25, 2006, 05:03:24 pm »
Aye, I looked into it before writing any code at all.  The time difference is negligible since invoke won't be called enough for the difference to be perceivable by a human.  I choose reflection over interfaces for greater power when handling events.

Incidently, I am a big fan of C# and have already written something that does much of this using delegates.  However, this particular program I intend on running from my server which is running debian.  I don't know enough about Mono to know whether I could write the entire program in C# and have it work perfectly so this is easier :)

Offline MyndFyre

  • Boticulator Extraordinaire
  • x86
  • Hero Member
  • *****
  • Posts: 4540
  • The wait is over.
    • View Profile
    • JinxBot :: the evolution in boticulation
Re: [Java] Efficiency/best practice dilemna
« Reply #9 on: July 25, 2006, 06:35:47 pm »
Incidentally, on that graph, the call is probably .00001seconds, or less, which would make the invoke like .00001seconds, which is still nothing. 

When it comes to making a decision between programming and speed, choose programming.  With modern computers, a small speed difference rarely matters. 
Excuse me?  Invocation through RMI and Reflection could hardly be called a tradeoff between "programming and speed," it's more like a tradeoff of "programming and speed against convenience."

Using Reflection (which is intended to provide information) to call code is like running code in the data segment.  It might not be safe, it shouldn't be practiced, and it goes against the paradigm of the programming language you're using (Java is object-oriented; using Reflection is going against the "black-box" theory).

I'm not saying it's the wrong way to go about this, I'm just saying that calling this "programming" in a tradeoff of "programming and speed" is sorely inaccurate.
I have a programming folder, and I have nothing of value there

Running with Code has a new home!

Our species really annoys me.

Offline iago

  • Leader
  • Administrator
  • Hero Member
  • *****
  • Posts: 17914
  • Fnord.
    • View Profile
    • SkullSecurity
Re: [Java] Efficiency/best practice dilemna
« Reply #10 on: July 25, 2006, 08:02:22 pm »
Excuse me?
Why does everybody assume they'll be excused?  What if I choose not to allow somebody to be excused for, say, farting?  Do I get to kick them out of my house or something?  But anyways...

Invocation through RMI and Reflection could hardly be called a tradeoff between "programming and speed," it's more like a tradeoff of "programming and speed against convenience."

Using Reflection (which is intended to provide information) to call code is like running code in the data segment.  It might not be safe, it shouldn't be practiced, and it goes against the paradigm of the programming language you're using (Java is object-oriented; using Reflection is going against the "black-box" theory).

I'm not saying it's the wrong way to go about this, I'm just saying that calling this "programming" in a tradeoff of "programming and speed" is sorely inaccurate.
I'm not sure why you're talking about RMI.  So I'll just ignore that for now, and assume we're talking about local code. 

I've never used the Reflection class before, so I didn't know what it was for.  Your post seemed to be warning him not to use it because of the speed difference.  I mean, why else would you give him a graph of the speeds?  So I was using a common line (especially useful considering the title of this thread), that you're better off with cleaner code than with faster code in almost all cases.  That's all I meant, it's a generic sentiment. 

Offline MyndFyre

  • Boticulator Extraordinaire
  • x86
  • Hero Member
  • *****
  • Posts: 4540
  • The wait is over.
    • View Profile
    • JinxBot :: the evolution in boticulation
Re: [Java] Efficiency/best practice dilemna
« Reply #11 on: July 25, 2006, 08:30:28 pm »
I'm not sure why you're talking about RMI.  So I'll just ignore that for now, and assume we're talking about local code. 
The "R" was meant for Runtime, not Remote.  Sorry.  In the context of reflection, for me, RMI means the way the execution environment invokes methods, that's all.
I've never used the Reflection class before, so I didn't know what it was for.  Your post seemed to be warning him not to use it because of the speed difference.  I mean, why else would you give him a graph of the speeds?  So I was using a common line (especially useful considering the title of this thread), that you're better off with cleaner code than with faster code in almost all cases.  That's all I meant, it's a generic sentiment. 
Well, he initially wanted information about efficiency.  I posted a graph indicating why it was a better practice *and* more speed-efficient to use interfaces rather than dynamic method invocation.  You seemed to think that it was a tradeoff between good programming practice and speed; I was saying it was not.
I have a programming folder, and I have nothing of value there

Running with Code has a new home!

Our species really annoys me.