On Fri, 26 May 2006 20:00:54 -0400, Harry Vennik <[EMAIL PROTECTED]> wrote:
[CUT] >> 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! > Karel proposed to have 'tags', to be able to tag each user, and be able to sort users by tags, it would be the same as groups, but internal to amsn, I still didn't understand what he meant and why not use groups as the 'tags' feature he's asking... >> 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 > yes, indeed :) > 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... > no, it's not about the GUI.. look at the MSN protocol, we get a LST for each contact, but before that, the first step is receiving all the LSG... we get LSG to 'create' our group objects, then we get LST for each contact with one argument speicifying the list of groups that contact is part of. A group can have multiple properties, first, its name, second the contacts it contains, it can have some stuff like notes 'per group', not just per user, etc... yes, it IS a GUI thing, but it is considered as an object in the protocol, and it has its own info.. do you see a contacts.tcl file, no ? but we do have a groups.tcl.. read the proc names in it, you'll understand the need to have a group object and a groupmanager object. we should forget about the GUI now, we assume we create a headless application, or just the protocol library.. we would still need to separate the groups as objects... and I think the groupmanager is a good idea to keep the trash in the same place.. but did you notice something, in the protocol, there is no cross referencing, only the contacts have a reference to the group, not the group to the contact... which seems to naturally aprove what you're just saying. if we go that way, the groupmanager will be a lot simpler, but it will still be a needed object to facilitate the copy/move of users amongst groups and the easy retreival from a group to its 'children'.. and that, still independantly on the GUI. > [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. > Humm, maybe we misunderstood each other here, I guess you're thinking about the 'mass message a group' thing, no ? or maybe I just didn't understand what you meant (it's 4AM here:S).. a group, is as you said a graphical thing to group users together, you can collapse/expand a group, right clock on it and 'block all users from this group', etc... but it actually doesn't care, AT ALL about when you start a chat (apart if you use tabbed chat windows and you group your convos by group in which case the group name should appear in the titlebar. > 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. > humm.. I don't like the naming :P and yes, I already created the eventsystem, and it already sends the calling object as the first param. >> > 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. > humm.. yes, as I said, it's matter of choice, but also, now that I implemented the eventsystem's code, I realized that my design was *maybe* better, because I bumped into a problem... you have a 'listener', you do an "on event do_this", so your 'do_this' gets added to the list of things to do... now imagine your object gets destroyed (contact is deleted for example, or moved from one contact to another), ouch your do_this will still be called, which is bad I think... in other words, you can say "on this, do this", but how do you say "on this, don't do this anymore", in terms of a method name, I can hardly think of how to do it.. so instead I made these 2 methods : $eventsystem {listener add} {event command} $eventsystem {listener remove} {event command} in the 'listener' design, you are just someone listening to an event, you can add yourself, and remove yourself. >> > 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. > > Yes I understand, but I think inheritance is for 'real OO', and in tcl, it's good to delegate stuff... The only thing I think is usefull with inheritance as you said is that you are in the same context as the base object. But the problem is that you can't inherit from a button if it's not a snit object itself (or tcl incr), you can't inherit from a frame and let it do all you want, but only enhance it a little, you can't inherit with incr tcl, from a snit object, etc.... don't forget that with tcl/tk it's not java/c++/.net if you want to execute in the same context, do this : uplevel 1 { } at the start of your methods, and you're done! ;) well.. maybe not, but hey, who cares? :P -- KaKaRoTo _______________________________________________ Amsn-devel mailing list Amsn-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/amsn-devel