Dev Meeting Log 20090815

From PCGen Wiki
Revision as of 00:54, 19 February 2014 by Tom Parker (talk | contribs) (Created page with " ==Summary== * The PlayerCharacter object will be broken into facets * Facets draw in events from the graph and share updates with events * Facets operate with a global cach...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Summary

  • The PlayerCharacter object will be broken into facets
  • Facets draw in events from the graph and share updates with events
  • Facets operate with a global cache and have a character ID passed in so that they know what they are operating on
  • Wiring up should be compatible with Spring, but we probably should put together an example to show people the difference in something they can poke at

Transcript

[08:02] *** #pcgen: [Code_SB]james karianna cpmeister [Arch_SB]thpr DrewM @Zaister
[08:07] [Arch_SB]thpr: by the way, can I assume everyone has read the PlayerCharacter design changes thread?
[08:08] Zaister: skimmed it
[08:08] Zaister: bringin it up now :
[08:08] [Arch_SB]thpr: http://tech.groups.yahoo.com/group/pcgen_developers/message/86
[08:08] [Arch_SB]thpr: for anyone who wants to pull up the thread
[08:08] Zaister: thx
[08:12] [Arch_SB]thpr: so the background here is that we wanted to walk through a discussion around how we structure PlayerCharacter going forward
[08:13] [Arch_SB]thpr: Currently, PlayerCharacter is pretty monolithic, and somewhere on the order of 20K lines
[08:13] [Arch_SB]thpr: I find that unwieldy
[08:13] [Code_SB]james: That's an understatement!
[08:13] [Arch_SB]thpr: I also think there are some other characteristics it would be nice to migrate away
[08:13] [Arch_SB]thpr: such as the universal setDirty system
[08:14] karianna: oh god yes please
[08:14] [Code_SB]james: :)
[08:14] [Code_SB]james: Oddly enough that one doesn't bopther me so much
[08:14] cpmeister: aye to that
[08:14] Zaister: oh yes
[08:14] [Arch_SB]thpr: to do that, we need to migrate to something that has a more "fine-grained" control
[08:15] [Code_SB]james: We will need to have a change notification system of some form
[08:15] [Code_SB]james: yes
[08:15] [Arch_SB]thpr: absolutely
[08:15] [Arch_SB]thpr: so I think that leads to starting from the Graph structure and looking at what it has/does
[08:15] [Arch_SB]thpr: basically the graph serves a few purposes
[08:16] [Arch_SB]thpr: stores what the PC has access to
[08:16] [Arch_SB]thpr: (theoretical information like LANGBONUS)
[08:16] [Arch_SB]thpr: stores what the PC has granted to it (e.g. AUTO:FEAT)
[08:16] [Arch_SB]thpr: and includes the source of what granted the information (relevant for things like REMOVE:FEAT|CLASS.Fighter)
[08:17] [Arch_SB]thpr: therefore some simple tests, like presence, we dont' need to worry too much about
[08:17] [Arch_SB]thpr: the Graph knows that info
[08:17] [Arch_SB]thpr: it is more complicated things that we need to address how they work
[08:17] [Arch_SB]thpr: and we need to account for interdependency
[08:18] [Arch_SB]thpr: The example that I used in the note and that I think is valuable as a simple walkthrough is HANDS
[08:18] [Arch_SB]thpr: it needs to know Templates and Race
[08:18] [Arch_SB]thpr: and if either of those change
[08:18] [Arch_SB]thpr: (assume for a moment that the HandsFacet doesn't cache - we can come back to that)
[08:19] [Arch_SB]thpr: My initial assertion is that the Graph can fire changes out of the graph in a listener/event system
[08:19] [Arch_SB]thpr: There is already a GraphChangeMonitor class in the cdom branch, so that code exists
[08:19] [Arch_SB]thpr: there can then be facets for each of the "native" objects (RaceFacet, TemplateFacet) that track the graph
[08:19] [Arch_SB]thpr: and can store the actual items (and notify other facets of changes)
[08:20] [Arch_SB]thpr: any thoughts/concerns/questions so far?
[08:21] [Code_SB]james: No problems so far
[08:21] [Arch_SB]thpr: ok
[08:21] cpmeister: question
[08:21] [Arch_SB]thpr: fire
[08:22] cpmeister: do these facets send events for everything or can they be tuned for specific things? Like rather than recieving all changes they can just recieve changes such as removal or additions
[08:22] cpmeister: asuming this is listening to a LIST
[08:23] [Arch_SB]thpr: there are 2 event systems (using event loosely for a moment)
[08:23] [Arch_SB]thpr: assuming we use the event/listener system that already exists, the graph would fire a change to all of the listeners (which would be a dozen or so base object facets) whenever the graph gained or lost a node or edge
[08:24] [Arch_SB]thpr: (I think you can actually listen separately, so they would really only monitor the node changes)
[08:24] [Arch_SB]thpr: the individual facets, TemplateFacet, for example, would then have to check if the change was a Template
[08:24] [Arch_SB]thpr: and would ignore the message if not a template
[08:24] cpmeister: ok, I was just trying to get an idea of how much of the UI facade structure is salvagable
[08:25] [Arch_SB]thpr: if it was a template, then it would send an add/remove message to others
[08:25] [Arch_SB]thpr: I would assume the TemplateList could implement ListModel
[08:25] [Arch_SB]thpr: so you could attach to it that way in the UI
[08:26] cpmeister: ok, good, that answers my questions :)
[08:26] [Arch_SB]thpr: err, I meant TemplateFacet
[08:26] [Arch_SB]thpr: yea, not trying to throw away the UI discussions we had Connor
[08:27] cpmeister: np
[08:27] karianna: OK, I'm happy so far....
[08:27] [Code_SB]james: and that facade system looks like it will work fairly well based on the playing around I have done so far
[08:28] [Arch_SB]thpr: so the second event system is coming out of the TemplateFacet into the other facets
[08:28] [Arch_SB]thpr: I use event loosely here
[08:28] [Arch_SB]thpr: because it may more properly be producer/consumer
[08:30] [Arch_SB]thpr: I think we should have in our mind that the facets may be running in separate threads
[08:31] [Arch_SB]thpr: but basically a TemplateFacet might send an event of a new (or removed) Template
[08:31] [Arch_SB]thpr: the HandsFacet could then use that to recalculate the # of hands on the PC
[08:31] [Arch_SB]thpr: obviously for some facets, they will draw on more complicated structures
[08:32] [Arch_SB]thpr: there will be a BonusFacet that is responsible for tracking BONUS objects
[08:32] [Arch_SB]thpr: it subscribes to all of the "native" facets and extracts BONUSes
[08:33] [Arch_SB]thpr: if no questions, I'll drop in a discussion of caching in the facets
[08:33] [Arch_SB]thpr: I think it's fair to say a facet should cache
[08:34] [Arch_SB]thpr: there are things we have that are pretty complex calculations that we don't want to reproduce unless the underlying data changes
[08:34] [Arch_SB]thpr: this leads to local vs global cache
[08:34] [Arch_SB]thpr: local may be easier from a standpoint of coding a single facet
[08:35] [Arch_SB]thpr: tends to eliminate casting
[08:35] [Arch_SB]thpr: however has some poor side effects
[08:35] [Arch_SB]thpr: couldn't be reused among 2 PCs
[08:35] [Arch_SB]thpr: so if someone has a whole party loaded, we end up with N copies of that facet in memory
[08:35] karianna: Which would be especially bad for gms
[08:35] [Arch_SB]thpr: also couldn't be reused if we try to get PCGen running on a web server, since local state is a big no-no in a web environment
[08:36] [Arch_SB]thpr: so while I like some of the characteristics of local
[08:36] [Arch_SB]thpr: the side effects are too big for me to really accept that as the best option
[08:36] [Code_SB]james: Agreed
[08:37] [Arch_SB]thpr: that leads to how the cache is accessed
[08:37] [Arch_SB]thpr: I suspect this has to be a property of events that are flying around
[08:37] [Arch_SB]thpr: we certainly dont' want a call to Globals. or anything
[08:38] [Arch_SB]thpr: and if changes are triggered by events, then the event needs to know the PC that is being processed
[08:38] [Arch_SB]thpr: or at least the cache of that PC
[08:38] [Code_SB]james: Or a character id has to be associated with the event to allow the facet to look up the right cache object
[08:39] [Code_SB]james: That then decouples the cache implementation from the events, which I think is desirable
[08:39] [Arch_SB]thpr: is there an advantate to using an ID vs. passing around the cache
[08:39] cpmeister: um, you lost me
[08:39] [Arch_SB]thpr: in how the cache is accessed, Connor?
[08:40] cpmeister: are you sending events out WHILE the PC is being changed?
[08:40] [Arch_SB]thpr: let me do a walkthrough assuming we're processing Hands
[08:40] [Arch_SB]thpr: user adds a Template to the PC
[08:40] [Arch_SB]thpr: this technically adds a Template object (with a link to the root) to the PlayerCharacter Graph
[08:41] cpmeister: k
[08:41] [Arch_SB]thpr: err, should be precise, "link" in this case is an edge originating at the root
[08:41] [Arch_SB]thpr: and leading to the PCTemplate
[08:41] [Arch_SB]thpr: as a result of that add, a NodeChangeEvent is fired
[08:41] [Arch_SB]thpr: knows ADDED
[08:41] [Arch_SB]thpr: knows the Template (let's call it HandsTemplate)
[08:42] [Arch_SB]thpr: RaceFacet gets the NodeChangeEvent
[08:42] [Arch_SB]thpr: ignores it
[08:42] [Arch_SB]thpr: TemplateFacet gets the NodeChangeEvent
[08:42] [Arch_SB]thpr: sees it adds a template
[08:42] [Arch_SB]thpr: adds it to the internal list (which triggers the ListModel based changes)
[08:42] [Arch_SB]thpr: then fires off a TemplateAddedEvent (or whatever it gets called)
[08:42] [Arch_SB]thpr: this TemplateAddedEvent is caught by HandsFacet
[08:43] [Arch_SB]thpr: which clears its internal cache (if it was caching) and recalculates the # of hands
[08:43] [Arch_SB]thpr: that help?
[08:43] cpmeister: yea, that cleared it up
[08:43] [Arch_SB]thpr: cool
[08:43] [Arch_SB]thpr: so back to ID vs. passing the cache
[08:44] [Arch_SB]thpr: I'm still trying to understand what the ID does differently
[08:44] [Code_SB]james: The main difference is that you remove knowledge of the caching mechanism from the events
[08:44] [Arch_SB]thpr: There are at least 2 ways the event can hold the cache
[08:45] [Code_SB]james: It becomes a local issue for the facets only
[08:45] [Arch_SB]thpr: first would be the event has .getCache()
[08:45] [Arch_SB]thpr: which returns a CacheObject
[08:45] [Code_SB]james: (with using an ID that is)
[08:45] [Code_SB]james: yep
[08:45] [Arch_SB]thpr: which has a .getCacheItem(Object cacheKey)
[08:45] [Arch_SB]thpr: (or Class cacheKey based on my email, but that's a detail ATM)
[08:46] [Arch_SB]thpr: this means CacheObject is at least an interface that is shared wtih the facets
[08:46] [Arch_SB]thpr: so high fanout of that interface
[08:46] [Code_SB]james: yep
[08:46] [Arch_SB]thpr: second implementation is the event has .getCacheItemFor(Class cacheKey)
[08:47] [Arch_SB]thpr: which makes the event carry a bit more knowledge and not be a hollow event
[08:47] [Arch_SB]thpr: but only puts the CacheObject interface knowledge into the event
[08:47] [Arch_SB]thpr: but ties the facet closer to the incoming event
[08:48] [Code_SB]james: The question for both of those is where does the event get the cache from?
[08:48] [Code_SB]james: and why should the event care about the cache?
[08:49] [Arch_SB]thpr: well
[08:49] [Arch_SB]thpr: for the first setup, since the CacheObject is exposed to the Facet, it can be used when events are constructed
[08:49] [Arch_SB]thpr: the "top level" facets can be given that from the PlayerCharacter object (or even during construction)
[08:50] [Arch_SB]thpr: in the second case, subsequent events would have to be given (And be able to reach into private info about) the source event
[08:50] [Code_SB]james: Right, so the facet will need to get it from another source anyway
[08:50] [Arch_SB]thpr: but doesn't it have the same issue with the ID?
[08:51] [Arch_SB]thpr: and just does something like Globals.getCacheObject(integer id)
[08:51] [Code_SB]james: Well, the id has some relevance to the event
[08:51] *** karianna has signed off IRC (Remote closed the connection).
[08:51] [Arch_SB]thpr: but the ID is unique to any PC
[08:51] [Arch_SB]thpr: and presumably doesn't change over the life of that PC
[08:52] [Arch_SB]thpr: (barring a global reset option somewhere)
[08:52] [Code_SB]james: Yep
[08:52] [Arch_SB]thpr: how would the first facets get or generate that ID
[08:52] [Code_SB]james: The vent is saying change x has happened to character y
[08:52] [Arch_SB]thpr: isn't it the same problem as getting the cache
[08:52] [Code_SB]james: Not really
[08:52] *** karianna has joined #pcgen.
[08:53] karianna: sorry
[08:53] [Arch_SB]thpr: can you walk through the hands example to show how the ID gets passed
[08:53] [Arch_SB]thpr: I'm not following how it's different
[08:53] [Code_SB]james: Sure
[08:53] [Code_SB]james: I'll just take a sec to pull up the example
[08:54] [Code_SB]james: user adds a Template to the PC
[08:54] [Code_SB]james: this technically adds a Template object (with a link to the root) to the PlayerCharacter Graph
[08:54] [Code_SB]james: as a result of that add, a NodeChangeEvent is fired
[08:54] [Code_SB]james: that event carries the character id and the affected nodes presumably
[08:55] [Code_SB]james: TemplateFacet gets the NodeChangeEvent, it can get the id from the event
[08:55] [Code_SB]james: TemplateFacet then fires a TemplateAddedEvent carrying that id
[08:56] [Code_SB]james: HandsFacet gets the event, reads the character id and then looks up the cache
[08:56] [Code_SB]james: The cache would be an object either injected at construction time (think Spring) or accessible via a global interface
[08:56] [Arch_SB]thpr: so HandsFacet would do something like CacheLibrary.get(id, getClass())
[08:56] [Code_SB]james: Yes
[08:57] [Code_SB]james: either using a static call or a call to an instance that it was told about earlier.
[08:58] [Code_SB]james: After a few years of working with Spring's dependancy injection model I'm a fan of having it as as an object that gets injected to the facet at construction time (or as part of initialisation)
[08:58] cpmeister: so every event ever generated by the Graph would have to have a unique ID?
[08:58] [Code_SB]james: no
[08:58] [Arch_SB]thpr: every PC has a unique ID
[08:58] [Code_SB]james: The id is the character id
[08:58] cpmeister: oh
[08:58] [Code_SB]james: yep
[08:58] [Code_SB]james: Which is something that makes sense for the UI
[08:58] [Arch_SB]thpr: the CacheLibrary is basically a DoubleKeyMap<Integer,Class>()
[08:59] cpmeister: why not use the Character object then?
[08:59] [Code_SB]james: yeah
[08:59] [Code_SB]james: Too heavy
[08:59] [Arch_SB]thpr: because if you use the PlayerCharacter you get tangles
[08:59] [Arch_SB]thpr: the Facets are known by the PC
[08:59] [Arch_SB]thpr: so they should never know about the PC
[08:59] [Arch_SB]thpr: class structure should be a directed acyclic graph
[09:00] [Arch_SB]thpr: it also exposes bad behavior
[09:00] [Arch_SB]thpr: meaning if you have the PlayerCharacter in all Facets
[09:00] [Arch_SB]thpr: you may be tempted to access it or change it directly as a quick hack to fix a bug
[09:00] [Arch_SB]thpr: and introduce a lot more problems than you fixed
[09:00] [Arch_SB]thpr: the cache or ID provides isolation so you can't do that
[09:00] cpmeister: ..but I thought that the PC was simply a key to query information out of the Graph? are the facets aware of what graph they are listening to?
[09:00] [Code_SB]james: The aim being to make doing the right thing (programatiically speaking) easier than doing the wrong thing
[09:01] [Arch_SB]thpr: Connor: yes, they would have to be listening to all graphs
[09:01] [Arch_SB]thpr: James: exactly
[09:02] [Arch_SB]thpr: well, I should correct that
[09:02] [Arch_SB]thpr: Connor: literally no, a listener doesn't know who it's listening to, based on how a listener/event model works
[09:02] [Arch_SB]thpr: the graphs know the facets are listening, to be exact
[09:03] [Arch_SB]thpr: one graph per PC
[09:03] [Arch_SB]thpr: that help?
[09:04] cpmeister: so let me get this straight
[09:05] cpmeister: you are worried that the graph is going to try to assess its own changes?
[09:05] [Arch_SB]thpr: no
[09:06] cpmeister: then what is the ID protecting?
[09:06] [Arch_SB]thpr: My worry is keeping the facets ignorant of the total PlayerCharacter object
[09:07] [Arch_SB]thpr: so a facet doesn't read from the PlayerCharacter object
[09:07] [Arch_SB]thpr: rather it reads from the facet that should provide that detail about the PlayerCharacter
[09:07] [Arch_SB]thpr: a specific example:
[09:08] karianna: e.g. Facets get info from facets
[09:08] [Code_SB]james: So you effectively reduce the scope of the things that the facet needs to now about and at the same time document what the facet is interssted in
[09:08] [Arch_SB]thpr: something may be dependent upon a PC having two hands
[09:08] cpmeister: well, whatever, I'm sure the reason surpasses my sceptisism
[09:08] [Arch_SB]thpr: like equipping a two0handed sword
[09:08] [Arch_SB]thpr: so the system that makes that test looks at the HandsFacet
[09:08] [Arch_SB]thpr: so we know it's interested in the # of hands
[09:09] [Arch_SB]thpr: it means that system is no longer closely tied to the structure of the PlayerCharacter class
[09:09] [Arch_SB]thpr: meaning PlayerCharacter fans out to (is known by) a lot less classes
[09:09] [Arch_SB]thpr: this makes the system more flexible by isloating changes
[09:09] [Code_SB]james: @connor, no I think it is good to question these things - doing so has resulted in many problems being found early and thus being dealt with before they become intractible
[09:10] [Arch_SB]thpr: also means that facets can be tested without a mock object for PlayerCharacter running around
[09:10] karianna: Yup, questioning is good! You probably saw all of mine on the mailing list :)
[09:11] [Arch_SB]thpr: and that updates can be fine-grained to only when the PC
[09:11] [Arch_SB]thpr: 's # of hands changes
[09:11] [Arch_SB]thpr: and I have to agree, the questions are important
[09:11] cpmeister: would the ID system have to adapted for the UI?
[09:11] [Arch_SB]thpr: the actual programming is actually a small piece of any project
[09:11] [Code_SB]james: and we get to reduce recalculation
[09:11] [Code_SB]james: Connor, I wouldn't think so as it would know about the PlayerCharacter object
[09:12] [Code_SB]james: whichc would carry the id itself
[09:12] [Arch_SB]thpr: here's the rub
[09:12] cpmeister: oh, I see
[09:12] [Arch_SB]thpr: I originally said the TemplateFacet would implement ListModel
[09:12] [Arch_SB]thpr: for the UI
[09:12] [Arch_SB]thpr: it can't if there is one global TemplateFacet and the PC is an ID
[09:13] [Arch_SB]thpr: we need an interface to convert the Facets to a set of ListModels that are updated for each PC
[09:13] [Code_SB]james: Good point
[09:13] [Arch_SB]thpr: to isolate the UI from the facets
[09:13] [Code_SB]james: My assumption is that would be where the UIFacade would come in
[09:14] [Arch_SB]thpr: yes, I think that's where it goes
[09:14] [Arch_SB]thpr: I just hadn't adapted to all of the consequences of no local cache
[09:14] [Arch_SB]thpr: see? this is why we talk about things first
[09:14] [Arch_SB]thpr: :)
[09:14] [Code_SB]james: pc.getHandsFacet() would be the sort of thing I would expect the facade to use
[09:15] [Code_SB]james: It would seem odd to then have to say handsFacet.getNumHands(pcId)
[09:15] [Arch_SB]thpr: and then the facade knows the ID
[09:15] [Arch_SB]thpr: and can pass that into the HandsFacet to get the # of hands for the PC it "owns"?
[09:15] [Code_SB]james: for variables PlayerCharacter pc; HandsFacet handsFacet
[09:16] [Code_SB]james: int pcId = pc.getId();
[09:16] [Arch_SB]thpr: so let me double check here... the UI would see getHands()
[09:16] [Arch_SB]thpr: or facade.getHands()
[09:16] [Arch_SB]thpr: facade then does
[09:17] [Arch_SB]thpr: pc.getHandsFacet().getNumHands(pc.getID())
[09:17] [Arch_SB]thpr: I don't see a way around that
[09:17] [Arch_SB]thpr: unless I'm missing something
[09:17] [Code_SB]james: yeah, just seems a bit odd
[09:18] [Arch_SB]thpr: actually no
[09:18] [Arch_SB]thpr: pc.getHandsFacet() is wrong
[09:18] [Arch_SB]thpr: it's a facet repository that knows
[09:18] [Code_SB]james: or to go down the DI route, the facade already has trhe HandsFacet injected and then it just calls handsFacet.getNumHands(pcid)
[09:18] [Arch_SB]thpr: so it's repository.getHandsFacet().getNumHands(pc.getID())
[09:18] [Arch_SB]thpr: that's possible too
[09:18] [Arch_SB]thpr: but pc shouldn't have getHandsFacet()
[09:18] [Code_SB]james: yep, either would work
[09:18] [Arch_SB]thpr: because the facet isn't related to a PlayerCharacter
[09:19] [Arch_SB]thpr: but is reused
[09:19] [Code_SB]james: yeah, that was where I was heading too - good point
[09:19] [Arch_SB]thpr: well
[09:19] [Arch_SB]thpr: let's pause for other questions
[09:20] cpmeister: none here
[09:20] [Arch_SB]thpr: I suspect the next topic is how we end up tying these facets together, since we just brushed on it anyway
[09:20] DrewM: None here, very interesting stuff. :)
[09:20] [Code_SB]james: I've got one for Kar, Connor, Stefan and Drew - does this make sense?
[09:21] *** Papa-DRB_ has joined #pcgen.
[09:21] DrewM: I'm following the theories, beyond that it is interesting and seems to make sense
[09:21] cpmeister: yea, it does now
[09:21] DrewM: Oh, actually yes, Are we calling Edges Facets now?
[09:22] [Arch_SB]thpr: no
[09:22] karianna: It's making sense so far, but I _will_ be expecting a diagram from you gentlemen :), and we should keep this log somewhere so I can wiki it for future devs
[09:22] [Arch_SB]thpr: either James or I will post the log to _devel
[09:22] [Arch_SB]thpr: edges are part of the graph along with nodes
[09:22] [Code_SB]james: @Kar oh yes and a simple set of example classes to demonstrate will be useful too
[09:22] [Arch_SB]thpr: facets are what takes data from the graph and processes that into information about the PlayerCharacter
[09:23] DrewM: Tom - okay, that makes sense. Thanks.
[09:23] [Arch_SB]thpr: oookay, on to wiring this stuff up?
[09:24] karianna: @James - Great, we need to have clear pictures for new developers so we don't get hte wild west pcgen of old :)
[09:24] [Arch_SB]thpr: okay, wiring up
[09:25] [Arch_SB]thpr: one should assume we end up with on the order of 40+ facets
[09:25] [Arch_SB]thpr: that makes things interesting
[09:25] [Arch_SB]thpr: because we could have a rather nasty method to wire all this stuff up
[09:26] [Arch_SB]thpr: that is possible to do
[09:26] [Arch_SB]thpr: the open question - about which I have to admit I'm unsure - is whether there are other things we can leverage to help out
[09:26] [Arch_SB]thpr: e.g. Spring or another DI framework
[09:27] [Arch_SB]thpr: this would convert the long method into a long set of XML
[09:27] [Code_SB]james: Well, as I have alluded to I've been using Spring for this sort of problem for a couple fo years now
[09:27] [Code_SB]james: That would have the advantage of making the jump tothe web much easier too
[09:27] [Code_SB]james: yes
[09:27] [Arch_SB]thpr: which is kinda how this discussion started, since you were corrupting me with me Spring basics
[09:28] [Arch_SB]thpr: when we diverted into PlayerCharacter design
[09:28] [Code_SB]james: Although it is useful to remember that Spring philosophy is that nothing in the class should depend on Spring
[09:28] [Code_SB]james: and that particularly for testing you can create and inject the dependancies manually
[09:28] [Arch_SB]thpr: I don't think we have anything that would depend on Spring or the DI framework
[09:28] [Arch_SB]thpr: clearly we have a model we can do without
[09:29] [Code_SB]james: Spring just encourages you to do the right thing and document any dependancies
[09:29] [Code_SB]james: agreed
[09:29] karianna: Yeah I've been using spring the last year as well, it's a powerful framework but you have to be careful not to use it to take shortcuts
[09:29] cpmeister: Spring is out of my area of knowledge...
[09:29] [Code_SB]james: So what we are talking here is the difference between
[09:30] karianna: @connor James can probably giver you a better primer than I, but let me know next time you're on IM and I can cover what I know of it
[09:31] [Code_SB]james: I'm making a comparison example to post in a couple of minutes
[09:31] [Arch_SB]thpr: If we go the Spring route, we also should do a simple mockup to get people into it slowly
[09:31] [Arch_SB]thpr: or I should say quickly ;)
[09:31] [Arch_SB]thpr: but to make it clear is the point
[09:31] *** Papa-DRB_ has signed off IRC (".").
[09:32] cpmeister: @kar thanks, but I can read up on it if it becomes crucial to know
[09:33] [Code_SB]james: ok, so the repository way would be
[09:33] [Code_SB]james: public void createFacets() { TemplateFacet tf = new TemplateFacet(); HandsFacet hf = new HandsFacet(); hf.setTemplateFacet(tf); // make these facets available for retrieval some how, probably by fields in a repository. }
[09:34] [Code_SB]james: and the spring way would be
[09:34] [Code_SB]james: <bean id="tf" class="pcgen.core.facet.TemplateFacet"/> <bean id="hf" class="pcgen.core.facet.TemplateFacet"> <property name="templateFacet" ref="tf"/> </bean>
[09:34] [Code_SB]james: That assumes a dependancy on the template facet from the hands facet
[09:35] [Code_SB]james: In both cases the facet code is exactly the saem, it is just a matter of how you create the objects
[09:35] [Code_SB]james: The difference comes when somethign (e.g. the UIFacade) wants to use a handsFacet object
[09:36] [Code_SB]james: In the repository way it would use a repository.getHandsFacet() call
[09:36] [Code_SB]james: and in the spring way it would itself be a spring bean with a definition in the xml and a regiustered property of handsFacet that gets supplied to it when the facade gets created
[09:37] karianna: Slight typo above james
[09:37] karianna: 2nd bean should be a HandFacet class
[09:37] [Code_SB]james: yep
[09:37] [Code_SB]james: <bean id="tf" class="pcgen.core.facet.TemplateFacet"/> <bean id="hf" class="pcgen.core.facet.HandsFacet"> <property name="templateFacet" ref="tf"/> </bean>
[09:39] cpmeister: the Spring framework looks quite similar to output of java.beans.XMLEncoder. :-/
[09:40] [Code_SB]james: Not too supriising as Spring is designed around POJO support
[09:41] [Arch_SB]thpr: any thoughts or concerns on connections?
[09:42] [Code_SB]james: connections?
[09:42] [Arch_SB]thpr: wiring
[09:42] [Arch_SB]thpr: whatever one calls it
[09:42] [Arch_SB]thpr: connecting the facets
[09:42] [Code_SB]james: right :)
[09:42] cpmeister: I have one
[09:42] cpmeister: I can sum it up in one word
[09:42] cpmeister: Threads
[09:42] [Arch_SB]thpr: meaning what?
[09:43] [Code_SB]james: My only main suggestion is to stick to the DI philosophy and that leaves us open to different implementations should we need to
[09:43] cpmeister: or is that question getting ahead of discussion?
[09:43] [Arch_SB]thpr: I'm not sure if it's a comment, concern, or what you mean by threads
[09:43] [Code_SB]james: Meaning what happens if I call getNumHands as the handsfacet is processing an event?
[09:43] cpmeister: how many would there be and how would they interact?
[09:44] [Arch_SB]thpr: okay two issues there
[09:44] [Arch_SB]thpr: Connor:
[09:44] [Arch_SB]thpr: simple answer is that the listener/event system becomes producer consumer
[09:44] [Arch_SB]thpr: which allows the facets to run in different threads
[09:44] [Arch_SB]thpr: # is arbitrary
[09:44] [Arch_SB]thpr: that then brings up another issue
[09:44] [Arch_SB]thpr: which is
[09:44] [Arch_SB]thpr: what if a second template is added before processing for the first one finishes
[09:45] [Arch_SB]thpr: that's tricky to handle
[09:45] [Arch_SB]thpr: there are a few options and I'm not sure we'll have time to walk through them
[09:45] [Arch_SB]thpr: I can post to _devel on that topic
[09:46] [Code_SB]james: uggh queuing
[09:46] [Code_SB]james: Yeah makes sense
[09:46] [Arch_SB]thpr: James:
[09:46] cpmeister: since some templates exclude others once added, adding and updating template information would have to be atomic
[09:46] karianna: It's something we deal with in the asynch messaging world, interesting topic....
[09:46] [Arch_SB]thpr: getNumHands could either be synchronized
[09:46] [Arch_SB]thpr: or
[09:46] [Arch_SB]thpr: it simply runs the processing twice
[09:46] [Arch_SB]thpr: it's technically a performance hit, but doens't corrupt
[09:47] [Code_SB]james: Seems ike a good topic for the next meeting or a list discussion
[09:47] [Arch_SB]thpr: yes, I think this is bigger than what we can do now
[09:47] karianna: Yep
[09:47] [Arch_SB]thpr: lots of issues as we go multi-threaded
[09:48] [Arch_SB]thpr: which are beyond breaking PC into facets
[09:48] [Arch_SB]thpr: so let me check that we're all on the same page
[09:48] [Arch_SB]thpr: no concerns with facets as defined drawing in events from the graph and sharing updates with events
[09:48] [Arch_SB]thpr: (assuming 1 thread)
[09:49] [Arch_SB]thpr: wiring up should be compatible with Spring, but we probably should put together an example to show people the difference in something they can poke at
[09:49] [Arch_SB]thpr: anyone disagree?
[09:50] cpmeister: nope
[09:50] [Code_SB]james: nope
[09:50] [Arch_SB]thpr: Kar? Stefan?
[09:50] [Code_SB]james: The other main topic was how do we manage the cache used by facets
[09:51] [Arch_SB]thpr: ah, yes
[09:51] [Arch_SB]thpr: global cache, passed by ID
[09:51] [Code_SB]james: cool
[09:51] [Arch_SB]thpr: the difference from that to passing the cache is painting a shed, IMHO
[09:51] [Arch_SB]thpr: the ID is probably clearer and does allow injection of the cache owner, which is a benefit
[09:51] [Arch_SB]thpr: if we go Spring route
[09:52] [Arch_SB]thpr: ok, I have to run
[09:52] karianna: I'm happy
[09:52] [Arch_SB]thpr: have a good morning/afternoon/evening/night everyone
[09:52] [Code_SB]james: I'll post the log later this monring, probably with the summary at the top followed by the log and a little tidying up
[09:52] cpmeister: later Tom
[09:52] [Arch_SB]thpr: thanks, James
[09:53] karianna: You to, great discussion! Thanks James
[09:53] karianna: night all