Re: MethodClosure (BCEL Delegator implementation)

Leo Sutic <[email protected]>
Newsgroups gmane.comp.jakarta.avalon.apps.devel
Message-ID <5.1.0.14.2.20021222125211.00bb29c8__7677.23214016787$1040558991@mail.sutic.nu>
 > I'm not sure what the use case for comparing two delegates is
 > anyway. Can you give me some?

In a multi delegate (called event in C#), you have the possibility to add 
or remove delegates. For example, consider a button in a GUI. Anyone can 
add a delegate to its OnClick event:

     ...
     Button myBytton = new Button ();
     myButton.addOnClickHandler(
         MethodClosure.newInstance(
             Button.OnClickHandler, this, "myButtonPressed"));
     myButton.addOnClickHandler(
         MethodClosure.newInstance(
             Button.OnClickHandler, this, "generalClickHandler"));
     ...

Which will cause the myButtonPressed and the generalClickHandler methods to 
be called when the button is clicked.

The question is now: If you add the same method twice, will it be called twice?

     ...
     Button myBytton = new Button ();
     myButton.addOnClickHandler(
         MethodClosure.newInstance(
             Button.OnClickHandler, this, "myButtonPressed"));
     myButton.addOnClickHandler(
         MethodClosure.newInstance(
             Button.OnClickHandler, this, "myButtonPressed"));
     ...

Excalibur's implementation (and C#) says no. The MultiDelegate has a 
set-like behavior, so that adding a delegate once is the same as adding it 
twice. The code above is therefore equal to:

     ...
     Button myBytton = new Button ();
     myButton.addOnClickHandler(
         MethodClosure.newInstance(
             Button.OnClickHandler, this, "myButtonPressed"));
     ...

as the second add has no effect.

In order for the MultiDelegate to figure out if it already has a delegate 
in its collection of delegates, it must have some method of comparing them. 
And that's where equals() and hashCode() comes in.

 > Sure. Although if it does happen that CGLIB gets used by Avalon, there
 > would need to be a good rationale and understanding of the general
 > usefulness of each class that gets moved over. For my benefit, it would be
 > helpful to have a summary of which classes are under consideration, how
 > they fit into the Avalon framework at a macro level, and how they could be
 > useful outside of Avalon.

Of course. Avalon is roughly divided into two parts: Framework and the 
rest. Framework is the "bare minimum" - it is usually just interfaces and 
the contracts surrounding them. We're not about to put in a CGLIB 
dependency here. We can use delegates without introducing a CGLIB 
dependency - all that will be in Framework would be the delegate 
interfaces. How the actual delegates are created is left as out-of-scope 
for Framework.

Then you have "the rest": Here you'll find Phoenix, Fortress and all the 
other "big things" as measured in lines of code and features. A BCEL 
dependency here is OK.

The classes we would donate are usually those that have very well-defined 
contracts. For example, you can't change a delegate into something that 
would break Avalon and still keep it a delegate.

 > I understand now. I'll go ahead and make the factory protected, and
 > change the name to something less likely to conflict (for example
 > "cglib_newInstance", which is already used in another class for this same
 > reason).

May I suggest the name "$cglib_NewInstance"? I think I read somewhere that 
identifiers starting with a "$" are a no-no for programmers, meaning that 
we can use it for this purpose. (Should Sun start including a method by 
that name there's just one place where it is used, and if someone else 
creates a delegate with that signature, well, then that person is clearly 
in the wrong.)

 > The problem is that invoking the constructor of the generated class would
 > require reflection, which will give back a lot of the performance gains.
 > The only other alternative is to generate yet another class whose sole
 > purpose is to call the constructor of the delegate, but I do not think it
 > is worth it.

I value startup time less than runtime. A delegate will only be created 
once, but may be called thousands of times. However, with a name that is 
forbidden for general use (cglib_newInstance or $cglib_newInstance), the 
collision scenario should not happen, so I think this is a non-issue.

/LS
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.