Op donderdag 25 mei 2006 22:01, schreef Youness Alaoui:
> On Thu, 25 May 2006 15:06:23 -0400, Harry Vennik <[EMAIL PROTECTED]>
>
> wrote:
> > Op donderdag 25 mei 2006 17:08, schreef Youness Alaoui:
> >> On Thu, 25 May 2006 06:55:10 -0400, Harry Vennik <[EMAIL PROTECTED]>
>
> [CUT]
>
> >> and have all those events get directed to the same function ? it's
> >> easier
> >> this way. (also, we want to abstract gui and protocol rigght ? so the
> >> protocol shouldn't know what *is* a visual data.. for the
> >> abook/contact/account/protocol/whatever, the psm is just an option of a
> >> contact, it doesn't know if our GUI shows the PSM or if it's hidden...
> >
> > Hehe, I had to give it some name, at first I called it
> > contactDataChange, but
> > then I thought that might be too general, but I still wanted to limit the
> > number of events, because the change of a nick, psm or dp will be of
> > interest
> > in the same places most of the time.
>
> WOOOOOW, so far we agree ! :) it's rare that both our brains are in sync
> on a design :P cool :)
>
> >> > Also, about the abook structure: do not have group objects contain
> >> > contact objects (however, in the gui part, a clgroup should contain
> >>
> >> one or
> >>
> >> > more clcontact objects).
> >> > In the abook part, a contact should keep references to the groups it
> >> > belongs to, and the abook object itself keeps references to all
> >>
> >> contact
> >>
> >> > objects and all group objects (either implicit or explicit), to pass
> >>
> >> on
> >>
> >> > the calls that modify contact or group data.
> >>
> >> no, I think crossreferencing is better, but I understand your point..
> >> the
> >> contacts should have the groups they belong to (groups, as in objects,
> >> not
> >> the groupids, if we want the group ids, we'll loop through the objects
> >> and
> >> do a cget -gid), but the groups should also have a reference to the
> >> contacts they have.. think about it, you want to mass message a group,
> >> so
> >> you do
> >> $group getContacts
> >> and it does :
> >> method getcontacts { } {
> >>   set account $parent
> >>   set contacts [$account getContacts]
> >>   set my_contacts [list]
> >>   foreach contact $contacts {
> >>       set groups [$contact getGroups]
> >>       foreach group $groups {
> >>          if { $group == $self } { lappend my_contacts $group }
> >>      }
> >>   }
> >>    return $my_contacts
> >> }
> >>
> >> it does seem to work, but is not really the way to do it, a group is
> >> there
> >> to 'group' smoething, so it should have children, if a group has no
> >> children, then it's empty.
> >> Question is a contact's parent is the group or is the account.. I'd say
> >> the account, simply because you can be part of multiple groups, but only
> >> one account defines you.
> >
> > You know, I hate cross-referencing! Why? because it is always redundant,
> > and may thus cause errors (e.g. a contact referring to a group, but that
> > group not to the contact). Yes, that would be simply a bug, but still that
> > is what's likely to happen with redundant data.
> > And how to code it cross-referencing in a safe way? The group cannot
> > access contact data and the contact cannot access group data. So if you
> > have [$group contact add $contact] $group will have to call some method on
> > $contact... let's say [$contact group add $self]... that wil work. But now
> > someone does [$contact group add $group] somewhere in the code, and things
> > are messed up... so we will need to have $contact call [$group contact add
> > $self] and the {contact add} method on the group should refuse adding a
> > contact that is already there (or we will have an endless loop)...
> > Hmm, you can also simply forbid the use of [$contact group add $group],
> > and pray noone will sin...
> >
> > So, that's one side of the story...
>
> Humm.. again, we agree :D don't say wow yet, because I'm convinced that
> cross referencing should be avoided, but not yet convinced on how you want
> to do it.. this is another design phase that needs some brainstorming, if
> we think about, what is a group ? it's an important thing, it's not only a
> GUI thing, I mean, you don't delete a contact from your CL, you delete it
>  from groups, you can have a same contact in more than one group, and you
> can have a contact in no group too.. a group contains contacts, so it's a
> parent, a contact doesn't contain groups, so it shouldn't be a parent, the
> reference goes from group to contact.. so it's account->group->contact and
> account->contact (for no group), but group is not a *real* parent, since a
> contact can be part of multiple groups, so it's a total mess..
Indeed it seems a real mess, but we have to take that 'as is', and try to make 
it the best we can. Anyway, what's making the groups important? Really 
nothing. Of course you work with them on the protocol side, they need to be 
there to make it possible to have them in the GUI. Otherwise you get the same 
as on skype: you go to another pc and the groups are gone... (early versions 
of skype even stored the contact list on the pc only!) So: groups are used 
everywhere from protocol to GUI, but their reason to exist is still the GUI! 

> we could either have cross referencing, making sure that the consistency is
> kept by having what you said, $contact add group -> $group add contact ->
> $contact add group, where the last one wouldn't do anything because the
> group is already known as containing that contact.
> but it's not the only thing, there's also copy from one group to another,
> moving a contact, deleting a contact from a group, etc...
> Checking for consistency would be a maze if we did it inside group and
> contact... so how about having a 'groupmanager' object, its sole purpose
> would be to manage the contacts and the groups relations between each
> other, so the 'consistency' wil lbe done in a single place.
> we'd have one groupmanager object per account, and we could either have
> the $contact and $gorup objects have a reference to the groupmanager or
> simply do each time a [$account cget -groupmanager] (or do it once in the
> constructor if we make that option readonly).
> The groupmanager object would take care of that cross referencing (without
> having a rela xref) and will allow us to easily [$groupmanager contact
> move $oldgroup $newgroup] or [$groupmanager contact copy $togroup].. it's
> internal structure would need a brainstorming too, I like to use arrays,
> because it's faster than a list (hashtable) and is easier to reference
> than doing an lsearch/lindex/lrange... so how about 2 arrays, one with the
> contacts, one with the groups, the key is the name of the object, the
> value is the list of children.. so
> method getcontacts { } { return [array names contacts] }
> method getgroups { } {retun [array names groups] }
> method contactHasNoGroup {contact} { return [expr [llength [set
> contacts($contact)]] == 0 ? 1 : 0] }
> method contactInGroups { contact } { return [set contacts($contact)] }
> etc...
> there will be cross referencing, but inside one object between two arrays,
> not cross referencing between multiple objects,e ach referencing each
> other... you like it, or it needs more brainstorming ? I just popped that
> idea out of my head, so it's far from being the perfect design plan..
Not bad thougt of, but indeed the internal structure of the group manager is 
the difficult thing, but at least you got the garbage in the bin :-P

But I still stick to groups are there for the GUI, and nothing else. Think of 
it, this is real simple, I wonder why I didn't think of it sooner... We need 
to go further, and eliminate the group objects! We just keep a list of gids 
as a propery of each contact object, and one array with group names in the 
account object (each element in the array having the gid as key and the group 
name as value). And you'll see, we don't miss a thing here!

If you really want group objects, just store a reference to one or more of 
those in the contact object (instead of the gid list). See here what we've 
got: reference contact -> group!

And what reason do we have for group->contact? None! We got lured into 
thinking we need it, because of... the GUI! But we really don't need it, 
because we can add a contact to the CL widget object, and it is then sent to 
a clgroup, depending on the gids or group references it has...

[CUT]
> > Within the contact object [$self fire nickChange] will fire the event.
> > Please note that nothing in the clgui will need to listen for events on
> > all contacts, but some other gui parts may need to do so, so we might
> > allow to do so by [$account on contactNickChange "$self
> > nickChangeMethod"], and have in the Account class something like [$contact
> > on nickChange "$self fire contactNickChange $args"] for each contact being
> > added. 
>
> no, I don't like that, I'd prefer to have
> $acount on contactadded "$self new contact"
> method {new contact} {contact} { $contact on nickChange "$self
> nickChangeMethod" }
>
> you have tha tin java too, I used it once, I have a listener on something,
> and I have a listener on the toplevel window, a ComponentListener that
> adds my listener to each component created...
>
Yeah, now you're talking, this makes the cross reference all gone!
What about this pseudo-code: 

# Getting rid of eval too, using [$source on $event $listener $method] instead

::snit::widget CLGroup {
        option -group -readonly 1

        constructor { ... } {
                ...
                $account on contactAdded $self account_contactAdded
        }

        method account_contactAdded { account contact } {
                if { [$contact memberOf $option(-group)] } {
                        $self on startChat $contact inviteToChat
                }
        }

        #called when user starts chat with group
        method startChat {
                set $chat [$sbManager prepareEmptyChat]
                $self fire startChat $chat
        }
}

This way there is absolutely no need for CLGroup to retain an explicit 
reference to a contact in any way, it just uses it once to setup the events, 
and everything will work just fine. If at some event access to the contact 
object is needed again, the reference will be one of the args sent with the 
event.

Note the account parameter on method account_contactAdded, it is there only to 
illustrate a convention that a reference to the source of an event should 
always be passed to the event handler. A simplified method fire looks like 
this:

method fire { event args } {
        foreach { $listeners($event) as listener } {
                set $object [lindex $listener 0]
                set $method [lindex $listener 1]
                [$object $method $option(-partof) $args]
        }
}

The naming of the event handler methods is also conventional: 
sourcetype_eventname. This I adapted from the event handlers naming used 
in .NET, although it is slightly different because we're simply not on .NET 
here, and the exact same way is not usable here.

> > The methods 'on' and 'fire' are likely to be delegated to some event
> > system component, that will register the event.
>
> the on keyword I don't like, it's like "do this on this event".. actually
> a lot of things can happen on that event, the listener thing looks nicer,
> you know you're just a listener amongst others.. also the 'on' word could
> lead to confusion with 'on/off', but hey, who will code and use the events
> if he doesn't even know what 'on' is there for.. so it's really just an
> 'esthetical' choice.. I'd go with the listeners thing, but it's not
> something to debate on, as long as we decide ons something.
>
"do this on this event" is the exact right description of what it means isn't 
it? And I don't think it implies that the action to be taken will be the only 
one. And the confusion with on/off will be avoided by the context, and also 
every development team member will soon know that on is used to set an event 
handler.

> > Argh, why do we use snit??? We should use something base on inheritance
> > instead of delegation! Then we can have a common baseclass that has the
> > event system, and no need to do [delegate method on to ....] in every
> > class that needs to expose events. Shall we switch over to [incr Tcl]? It
> > is much better than snit.
> >
> > Harry
>
> oh oh... are we not agreeing on something?
> no, please, dont' start the debate on snit vs. incr tcl... I don't know
> snit, so I had to read the man pages yesterday, and I liked it a lot, I
> don't know about incr tcl, but snit looks really good, we need to delegate
> stuff, in our case delegating is better than inheritence.. it's kind of
> the same as inheritence, and it doesn't bother us to write 'delegate
> method on to eventsystem' and 'delegate method fire to eventsystem', two
> lines.. what did you loose ? you could even make it in a macro...
> in incr tcl, you'd also need to write that you inherit from the
> eventsystem anyways, so there's no real diff, apart from the fact that we
> already have snit implemented everywhere...

Hmm, I wasn't too clear indeed. The main problem with delegation is that you 
delegate the method to another object, while with inheritance you extend the 
class you're inheriting from, and the inherited methods will execute in the 
same context as the methods defined in the inheriting class.


_______________________________________________
Amsn-devel mailing list
Amsn-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/amsn-devel

Reply via email to