Sunday, September 21, 2008

[.NET vs Java] Event Handling: Are you sure pure OOP is always the simplest?


After a long time I'm again here for another post!
I will talk about event handling, focusing at first on .NET way to supply it, and then spending 2 words about the Java style.
What I want to talk about is delegates and how are they used...I know old good Giovacchia has already spoken about them in a previous post (here) but I wanna talk about them again.
Why?
I'm leaving for a while the Java world and walking through the .NET Framework (I have to take some Microsoft Certifications, 2 or maybe 3 exams in just 1 month and a half...sounds crazy but it's my task in the short term): this means I have to study, as for now, 2 book of about 1000 pages each one.
I'm not taking part in the war between Open Source Multi Platforms Java Conding and Mama Microsoft Windows-Platform Framework yet, but in this path toward the MS certifications I will try to catch what's good and what's not in both frameworks.
At a first sight (I'm about at the half of the first book) 2 years of experience in Java programming has helped me a lot, but I stopped a while learning about delegates.
I don't want to explain what actually they are (Giovacchia in his post said it perfectly), let's just say delegates are a kind of function pointers, and you have to subscribe a delegate to a particular event in order to make it running when that event is raised.
Because my memory is so short term (could it be Google's fault?), during the reading I made a simple schema to remember which key words to use when declaring a delegate and rasing your own event.


namespace HereIsMyDelegateNamespace{
. . .

public delegate void MyEventHandler(object o, System.EventArgs ev);

. . .

public class MyClass{
. . .
public event MyEventHandler MyEvent;
. . .

/* this method raises an event */
publlic ReturnType RaisingMethod()
{
System.EventArgs ev = new System.EventArgs();
. . .
MyEvent(this,ev);
. . .
}
}
}

namespace ConsumerNamespace{

public class Consumer{

public static void Main(string[] args)
{
. . .
MyClass m = new MyClass();
m.MyEvent += MyEventHandler(m_MyEvent);
. . .
/* from now on we can call a method
* or make an action which causes MyClass to
* raise the MyEvent event */

m.SomeMethodThatRaisesTheEvent();
. . .
}

public static void m_MyEvent(object o, System.EventArgs ev)
{
. . .
/* handles the event */
}
}

}


You have to remember few things:


  • The signature of the delegate has to be the same of your own handling method

  • The signature of the delagete has to contain 2 parameters: the first one is an object reference, that refers to the object that launches the event, and the second one must be a subclass of System.EventArgs (there are a lots of them implemented for the common events)

  • You can subscribe to an event using the overloaded operator += but you can also unsubscribe by using the -=

  • For common applications, you won't need to raise yourself an event, but just supply a method and subscribe it to the event (the method, as said, has to have the same signature of the needed delegate)


And what about Java?
Learning Java I actually never had the need to write down some code to remember how Event Handling works.
Why? There are no delegates, in the sense you need to specify an entire class as the delegate for that event. What does it happen when you need to subscribe to an event?
In that situation Java is more OO then .NET, indeed you only use your Handler Class (such as MouseListener class, but for the common events, e.g. such as Mouse and Keyboard, you have at your disposal tons of ready-to-use classes) to manage the event. In this scenario you call directly by the object that throws the event, an addXXXListener() or removeXXXListener(), and inside your class, in which you surely have an array of potential listeners, when you want to raise the event, you have to iterate manually by calling all the needed methods of the listeners subscribed.
IMHO Java is straightforward to the OOP, but you need more code, and .NET allow you by using delegate and event keywords not to think to the propagation of the event. Moreover, in .NET you won't need to specify an entire class to handle the event, bringing to a more concise code style.

I'm not as experienced in .NET as I'm in Java, so maybe in few weeks I will post the exact opposite kind of opinion, but as for now I'm feeling better using C#, as it seems it has taken the good in Java and brought it to a more powerfull level (I'm refering to the whole framework ofcourse and not to the language itself).


kick it on DotNetKicks.com

21 comments:

Tarelli said...

I've no experience with C# but I disagree with good old Scuffia. I prefere to have some basic blocks that allow me to build any compelx thing more than having many different blocks (=exceptions=more things to learn) specialized. Following that idea C# could introduce new syntax to the language to create singletons if they feel like. Would you like more public singleton class MyClass{...} because the code is more concise? Fuck hell no.

Johnny Idol said...

Good old Tarelli sure is a fine chap, but he sure likes to piss on good old Scuffia's flowers.

wekempf said...

1. Delegates/events are not limited to the (object, EventArgs) parameters. That's only a convention. You can have delegates/events that take any arbitrary parameters. Mind you, I'm not recommending you do this, just don't assume you are limited.

2. A delegate isn't just a "function pointer". For starters, there's MulticastDelegate. Then there's the fact that a delegate packages both the "function pointer" and the "target object" into a single concept.

3. Anonymous delegates and lambdas combined with closures are something else you need to come to grips with. These concepts provide a lot more power than you have available to you in (the current) Java.

Tarelli, that's a tired mantra. If you REALLY feel that way, then I assume you take issue with Java's synchronized keyword, or even with the monitors built into that language. For that matter, I assume you prefer to code in assembly language. Delegates and events *ARE* "basic blocks that allow a C# developer to build any complex thing". Nothing is hidden from the developer with this language feature.

Scuffia said...

Dear Wekempf I have no arguments to debate...as I said I have a long long jorney to the .NET understanding and surely I have a small idea of all things that are involved with the things I have written down...anyway this post was a kind of starting point of view about event Handling.
You are right that delegates have not to carry only 2 parameters (but is suggested); anyway in my poor experience it seems that as far as concerns event handling, delegates are method pointers, but that's all I can say (I haven't seen any other use yet!).
Moreover I disagree with Tarelli because the delegate/event paradigm can save you a bit of time and make more readable your code, as Event Handling is a common paradigm in current programming.
Fuck hell yes :D

wekempf said...

Scuffia,

I wasn't trying to debate you, only trying to supply you with some more knowledge about the topic.

I'm very sure you've used delegates already in a context where they are not simply function pointers. If you've added an event handler to a method on an object instead of just to a static method, you've already gone beyond simple function pointers. Seeing as how that's the most typical way to do things... I'll bet you've done it. :) Like I said, you're typical delegate is a bundling of a function pointer and an object pointer. This is an important distinction to make, because adding an event handler to a member function will create a reference to the object, and is a common cause of "memory leaks".

Scuffia said...

Thanks for your comments I appreciate your explainations! that's one of the reasons I'm happy that Giovacchia started this blog (I mean sharing knwoledge)...I hope there will be more and more people in the future willing to add some helpfull tips on my posts (that means a lot of people will have read it :D )

Tarelli said...

Wekempf, it's not a tired mantra. We all want to make things faster and we like when that is possible. A language has a syntax which is more or less complex. The tradeoff is complicating the syntax against make something faster and the debate is wheter you decide something is at the right level to do it or not. Synchronize is a keyword that you add to a method and gives incredible benefits, i.e. loads of things that you don't have to care about, so my thumb is up and your assumptions is wrong. In my opinion for delegates the benefits are not worth to justify them to be treaten as an exception. To make such functionality easier I'd prefere some function in the tool that adds for you a listening mechanism such as when you generate getters/setters. That's my taste for things.

fsilber said...

Delegates are a good approach (especially when using an IDE builder), but Microsoft's terminology and pedagogy suck (as usual). Terms are overloaded in metaphor-breaking ways.

Is an event something that happens, or is an event object a piece of fuctionality that gets executed _when_ something happens? Does the phrase "adding a delegate to an event" even make sense outside the limited world of Microsoft programming? No, it's nonsense -- it's as if President Bush in a speech told us that he is adding Condoleeza Rice (the delegate) to an earthquake (the event). This makes learning difficult for anyone who wants to understand at a level deeper than "monkey-see-monkey-do" (i.e., having to keep code samples on hand to remind you what is needed).

What we _should_ have is a language that provides closures (i.e., easy-to-construct single-method anonymous subclasses) as such, and event-handlers that are described as containers for closures -- to be called when the event of interest occurs.

"Add the delegate to the event" indeed!

fsilber said...

P.S. I meant to say "easy-to-construct single-method anonymous _inner_ classes" -- not "sub-classes".

wekempf said...

Tarelli,

We'll have to agree to disagree. Delegates are not simple syntactic sugar, nor something that a fancy IDE could render pointless. It fits every criteria you claim for synchronize (and I assume monitors). Sorry, you've supplied NO technical basis for your opinion, and so it's nothing more than your preference (nothing wrong with that, so long as you don't try to imply there is a technical reason behind said opinion).

The Java creators have a technical reason behind not having delegates in the language. It's not one I agree with, but at least there we can debate the topic on technical merits.

wekempf said...

fsilber,

Microsoft didn't "invent the names out of thin air". They are names of concepts accepted by the industry. Java uses the same names (apart from delegate, where they have no equivalent concept) in the same ways. There's very little difference in the language "adding a delegate to an event" (.NET) and "adding a listener to an event" (Java). I think you're trying too hard to find criticism.

wekempf said...

Oh, and .NET has closures, making your argument even more questionable.

Scuffia said...

IMHO a delegate is someone that acts for you when something (an event) happens...it doesn't seem so strange sintactically (Rice won't be a delegate for Bush for an earthquake but for a meeting I suppose it's right!).

Ricky Clarkson said...

"Would you like more public singleton class MyClass{...} because the code is more concise?"

No. I'd like it because it's less error-prone and less repetitive. Scala has it: object MyObject { }

fsilber said...

To wekempf: Java does not add listeners to events; it adds event handlers/listeners to event-producing components. The latter makes sense; "adding delegates to events" is gibberish.

Note that I am not criticizing the programming model of C#; in many ways I think it is a better language than Java. My criticism was limited to Microsoft's typical cavalier use (i.e. abuse) of the English language in the choice of keywords and identifiers. (It suggests to me that all too many of their developers' attention fails to rise above the level of operations and mechanisms to think in terms of declarative concepts.)

wekempf said...

fsilber,

I think you're splitting hairs. First, Microsoft doesn't say "adding delegates to events". They say "adding handlers to events". I think any English speaking person can easily comprehend that. If you want to get into silly word wars, I'd say that Java's concept of "listening to events" makes little sense. Events make noise? Observing the events makes a whole lot more sense.

Sorry, you're just spouting off, and contributing nothing with this argument. You're picking nits over something as unimportant as this, while YOU use terms and provide definitions that aren't accurate (referring to your remarks about closures). Takes away most of the emotional strength of your argument.

bobisbob said...

let's just say delegates are a kind of function pointers

It's a little closer to the truth to think of them as function pointers bundled with a "this" reference.

For common applications, you won't need to raise yourself an event

Once you're fully versed with C#, you'll find this not to be true. It's very common to create your own events in classes once you're comfortable with the concept.

In that situation Java is more OO then .NET

Not really. Delegates are objects in C#. In fact, the fact that methods themselves can be treated like objects in C#, unlike Java, would imply that it's more OOP.

Moreover, in .NET you won't need to specify an entire class to handle the event, bringing to a more concise code style.

More importantly, in C# you can listen to the same event from different sources in the same class, and handle them separately. (For example, listen to OnClick handlers from two buttons in the same window class.) In Java, you have to resort to inner classes (ugh) to do it.

tarelli: Following that idea C# could introduce new syntax to the language to create singletons if they feel like.

They did. static constructors. Works exactly like you'd expect: where static methods don't need an instance, the static constructor doesn't either. It will be called automatically before any method is called.

You could do that yourself, but it would mean wrapping every single method in your class with lazy initialization code.

In my opinion for delegates the benefits worth to justify them to be treaten as an exception

Personally, I think they're simpler to learn and use than anonymous inner classes. Once you throw in closures, they become very useful for a relatively small addition to the syntax.

fsilber: Is an event something that happens, or is an event object a piece of fuctionality that gets executed _when_ something happens?

It's something that happens (specifically, it is "raised"). The thing executed is an "event handler".

Scuffia said...

to bobisbob, it seems to me that treating methods as objects is a little forced concept, don't you think? anyway you're right saying that as Methods are objects, .NET is more OOP than Java (or at least as OOP as).
actually I've never had the need to raise an event, anyway I believe in you when you say that is a usefull and used pattern: let's see in my next works!

Johnny Idol said...

Scuffia - congrats for your English, it's horrible.

To raise events is common practice in .NET - even among butchers, you'll see

bobisbob said...

it seems to me that treating methods as objects is a little forced concept, don't you think?

No, definitely not. First-class functions have been a key part of programming since the discipline was first developed. They are core to the lambda calculus, which is one of the foundations of CS.

Scuffia said...

ok I have nothing more to say, you defeat me with le lambda calculus