Re: Consuming your own events.
Frans Bouma <[email protected]> Wed, 30 Jan 2008 10:36:03 +0100
| Newsgroups | gmane.comp.windows.devel.dotnet.clr |
|---|---|
| Message-ID | <007b01c86323$88193e20$984bba60$@nl> |
> Subclass hooks through On<SomeEvent> are great, but as you mentioned they
should
> be empty in the base class or only contain the code to raise a corresponding
public event.
> But what happens two or three levels further down the inheritance tree???
> This is just what the "brittle base-class" issue is all about, thereby not
stating that
> you shouldn't use inheritance but rather that you should use interfaces as
api:s and
> base-classes for internal implementation. (but then what about utility class
> libraries, and so the carousel goes, round and round and round and ...)
Erm... no. Say I have 3 classes, A, B and C, where A is the supertype
/ root of the hierarchy, B derives from A and C derives from B. A defines a
protected virtual method OnFoo which is empty and which is called when Foo
happens inside A. B overrides OnFoo to do things.
Now, when I write C, I could override OnFoo. However, by overriding
OnFoo, and not calling the base class, I thereby _change_ the behavior of the
base class (B in this case), this is what's called polymorphism. If I don't
want that, because I need the behavior of the base method in B, I call
base.OnFoo from my OnFoo override in C.
Sure, this needs attention, but so does a truckload of other things in
writing software. If you don't unsubscribe from an event, the event raising
object will keep you in memory... how many people know that and wonder why
they have to reboot their webserver every once in a while? ;)
Creating extensible classes is something which is key to a good
framework. Extensibility can be done in various ways: using plugged in objects
with implementations of algorithms, or for example through subclassing where
virtual methods are overriden. Sure, if you override such a method in a
subtype and you don't call the base' method, you might change the behavior of
that code, but is that really wrong? You're overriding it in C, and as C is
also B, you're actually simply changing what should be done when Foo happens:
instead of B's version, C's version of the handler has to be called.
> What you refer to as "Cancellable events" is actually two patterns: monitor
and blackboard.
I don't care how they're called in books or pattern websites. I have
never heard of 'blackboard' as a pattern, so I have no idea what it means,
though I do know what cancellable events are. I also think that it's not
monitor but observer.
> "Cancellable events" is an oxymoron since you can't cancel the already
executing event,
> But you can cancel the operation that is about to execute; this is a BIG
> difference!
'event' in 'cancellable event' isn't the RAISED .net event element
i.e., it's not the invoked delegate. It's the EVENT that WILL take place after
the raised .net element has been completed. So of course, cancelling something
that has been raised is stupid, but that's not what this is all about. The
EVENT which is cancellable is the event which will take place if you don't set
Cancel to true, e.g. the removal of an object from a list.
> To implement those patterns you should define a callback interface with two
method,
> Prepare and Execute (just as tx:s). (with events you get code that isn't
self
> documenting, requiring an interface to be implemented notifies the developer
that there are
> more plumbing active then just a plain-old-event).
Why do I have to implement a callback mechanism? That is IMHO pretty
complex in most cancellable event cases. Take the example of Removing an
element from a collection. In the Remove(item) routine, you do raise Deleting,
and after that you check if the cancel flag is set. If so, you return, if not
you proceed.
It can't get any simpler than that. However with a callback mechanism
it's pretty complex: what should I do in Remove(item) to tell subscribers that
an item is about to be removed and that I want them to tell me if that's
allowed? Call all objects in a list? Why not raise an event, which is
_exactly_ the same thing? What does re-implementing the event mechanism bring
to the table?
> And I definitely agree; event is the worst word ever, it has been used in
too
> many (bad) context's.
> MS decided to use .net events for most callback scenarios; I would argue
that
> this is a bad decision, probably based on their COM experience. JAVA has the
opposite
> solution with callback interfaces (and anonymous classes) for everything
(even worse).
I think you're mistaken about events being callbacks. Most events are
simply used for implementing the Observer pattern. Sure, you can write your
own objects to call on and implement that way the observer pattern, nothing
stops you from doing that. However it comes down to the same thing, so why
bother?
> I argue that simple one-off callbacks or just notifications should be events
> but complex protocols, such as cancel, should be implemented through
callback interfaces.
If it SIMPLIFIES things, why not. However I fail to see how it can get
SIMPLER than raising an event and checking a flag.
FB
>
> regards,
> --Daniel
>
>
> -----Original Message-----
> From: Discussion of development on the .NET platform using any managed
> language [mailto:[email protected]] On Behalf Of Frans Bouma
> Sent: den 30 januari 2008 08:50
> To: [email protected]
> Subject: Re: [DOTNET-CLR] Consuming your own events.
>
> > In this case the guidelines are right and sadly you are wrong =)
> > Your proposed solution isn't at all bad; but it is an even more complex
> > guideline then the one provided by MS, and even worse it is only your
> guideline =(
> > Here are a few fast comments:
> >
> > 1. the protected virtual OnTheEvent( ... ) shall only EVER be used to
raise
> > the event; no other logic.
> > If you implement other logic here, in a class designed for inheritance you
> are
> > in trouble.
>
> Erm...
> DataSourceControl.RaiseDataSourceChangedEvent
>
> So much for guidelines, eh? ;)
>
> Your reasoning is pretty flawed. The On<Event> methods can also be
> seen as methods which are called WHEN the event is raised or WHEN something
> happens (which doesn't necessarily have to be resulting in the raise of an
> event!)
>
> Your reasoning seems to be based on what's defined in Winforms.
That's
> all great, but .NET code is more than just winforms. I for example use
> On<SomeEvent> methods to make classes extensible so derived classes can tap
in
> the pipeline when an event OCCURS in the base class (and which perhaps
results
> in the raise of an event for subscribers). This thus means that
On<SomeEvent>
> methods are called by the method which raises the event, they in itself
aren't
> doing anything.
>
> > 2. Cancelable events are just a hack, remember that an event is a
multicast
> > delegate. Using OnTheEvent( ... ) you can control if the event is raised.
> Sure
> > you can get the invocation list and call the clients one at a time; but
how
> do
> > you handle the case
> > where a client further down the list cancels the operation??? Do you
> > compensate for it??? If so how???
> > Building a Before and After could work, but then you could as well Plain
Old
> > Callback interfaces (java/COM style) and really get down and dirty =)
>
> Do you really understand what cancelable events are all about?
They're
> not events which should be raised AFTER a fact, they're events which are
> raised BEFORE something is about to happen. E.g. an object is about to be
> removed from a collection. Right before the removal, you raise an OnDeleting
> event. All subscribers can check if that removal is allowed. If not, they
> cancel the event. But 'event' here isn't the OnDeleting event. 'event' here
is
> the 'removal'.
>
> So cancelable events are definitely not a hack, they're a great way
to
> create a disconnected system where subscribers can tap into a pipeline
without
> much effort.
>
> > 4. Using base classes are always pretty brittle; It is just simply very
very
> > very hard to design and implement a class correctly for inheritance.
>
> No it's not that hard. Operating a hammer is also not that hard, but
> if you smash something with it it might break, so be careful.
>
> FB
>
> ===================================
> This list is hosted by DevelopMentor? http://www.develop.com
>
> View archives and manage your subscription(s) at http://discuss.develop.com
>
> ===================================
> This list is hosted by DevelopMentor. http://www.develop.com
>
> View archives and manage your subscription(s) at http://discuss.develop.com
===================================
This list is hosted by DevelopMentorĀ® http://www.develop.com
View archives and manage your subscription(s) at http://discuss.develop.com