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.. 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..

Now the other side... your code example. Theoretically the cleanest way to do
it, but really not too efficient... So we need something else, and yeah,
cross-referencing seems a fix, or maybe reference the other way around (group to contact only) but then you have a problem with [$contact getGroups] and we need that too... So that's my second reason to hate cross-referencing: you
can hardly avoid it!

But in this case, I incorporated the way around the problem in my design by
referencing only from contact to group in the data layer (abook), but
referencing group to contact in the gui layer! (In the gui layer we have to reference group to contact because every clcontact is a child of a clgroup, and not the other way around). I cannot think of any situation where we might
want referencing from group to contact, except in the gui, because in
everything we operate on contacts, not groups. Groups are there only to
provide a way for users to group their contacts in the gui!

Okay, to get back to your example: Send message to a group? no prob... create a convo with all contacts in the group, and have fun! clgroup can do the job,
without using group.

Don't we still have cross referencing then? Yeah in some sense we do, but now it is spread across layers that already are supposed to monitor each other, and the cross-reference is checked because every change involves an event,
and the other side will get updated, and we're a lot safer IMO.


I see what you want here, but his can be VERY confusing, unless we had two teams, one working on gui, the other on protocol, they don't know each other, they don't touch each other's code, they don't even have access to it.. you're right about the contacts being children of the grops in the gui only, but in the protocol, it has no real meaning, they're not children, the gids are just a property of the contact... anyways, I don't know, tell me what you think about my proposal above, and we can talk about this over MSN later...
[CUT]
Of course, all the eventing system, listeners, etc.. wouldn't be rewritten
in each object, but will all use a single API from ::events:: that would
keep track of all the listeners for each object and would call the
listener's action method when an event is fired, etc...
also, this allows us to have a lot less functions processed each time an
event is fired... think about it, you have one contact that changes his
state, so ALL clgroup and clcontact widgets get called ? if you have 200
contacts in your list, then you'll have 200 "if { $contact != $parent}
return" called ?
What we have now is the same as having a global hook, it's
dangerous...What do you think ?

KaKaRoTo

I agree with the idea to have events per object. I had that idea myself too!
But I'd do it slightly different:
[$contact on nickChange "$self nickChangeMethod"]

yes, sure a command is better than a combination object/method 'cause we can add args, but it also adds some problems, how you're going to code it ?
eval $command $args
I've been using 'eval' so much in chameleon I know it's defects, it's really difficult to deal with lists, imagine you have the command "$self nickChangeMethod $email"
and the method is
method nickChangeMethod { email newnick }
now it all works, great, then we add the non-im contacts, the command becomes, once expanded a : "_self_variable_value nickChangeMEthod " ($email disappeared since it contains nothing) and the eval will result in the calling : [$self nickChangeMethod $newnick] which results in a really nice "wrong number of args" A solution would be to use [list $self nickChangeMethod $email] but i don't remember exactly, but this could also cause problems in other situations (where it will say "$self nickchangeMethod $email" is an unknown command, thinkin the 2 spaces and 3 words are all part of the command name (yes we can have a command name with a space, just list it). And there, the solution would be to use {$self... } instead of [list ..] but then, you get the error where the $variables are not expanded.. and I'm not talking about having a $args expanded from 1 list to 10 args or stay 1 arg... anyways
etc...
oups, sorry, I got really off topic here, anyways, using the command is fine with me but I'd prefer we think about it a little more if it's fine with you.

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...

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.

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...



--
KaKaRoTo


-------------------------------------------------------
All the advantages of Linux Managed Hosting--Without the Cost and Risk!
Fully trained technicians. The highest number of Red Hat certifications in
the hosting industry. Fanatical Support. Click to learn more
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=107521&bid=248729&dat=121642
_______________________________________________
Amsn-devel mailing list
Amsn-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/amsn-devel

Reply via email to