Tom's Arch "TO DO" List
Tom Parker, has identified the following items as "TO DO" list to continue progress on the Arch Front
- 1) Tighter integration on the Wiki to articulate what packages are part of which components in PCGen (references both directions don't exist today)
- 2) Visualisations of the graph concept on the wiki? We will need some examples for the "thought cases"/"counter-cases" that drive us to the current design
- 3) Commented sample of how to ties two nodes together with a relationship on the wiki would be very useful, though this is data structure dependent.
- 4) How to take advantage of the type safety now available in the core and truly improve performance
Tom Requested this come on the Wiki
--- In pcgen_developers@yahoogroups.com, "Martijn Verburg" <martijnverburg@...> wrote:
> > The reason for this is that I think PlayerCharacter could use some > > trimming. It would also be nice to plan for flexibility in non-d20 > > (or slightly modified d20) systems.
> > A very long term PCGen goal :)
...which can also be leveraged by places where MSRD is materially different from (R)SRD if you want something that is more tactical. :)
Imagine, for example, if PCGen didn't contain any alignment-based code when MSRD was running (+ performance :) ) and could actually detect PREALIGN: as a data bug in an MSRD set (+ data integrity :) ).
> > [caching]
> But instinctively I know that many role playing effects are of a global type (e.g. A template that removes all spell INT bonuses), it makes more sense to be able to change things in one place.
Uhh, I want to make sure a few things are clarified, because I'm confused by this comment.
First, no facet should ever be accessing another facet's cache. That creates a very tight linkage between Facets that is fragile and error prone. (it's also why we want to have the Class be a key to the global cache, so it takes some effort to get access to someone else's cache [we could make it harder by making the key an object that is stored as a private final Object cacheKey = new Object(); within each facet, but that's overkill & also wastes few bytes of memory in each facet, whereas the Class object already must exist in the JVM]).
Let me walk through this to make sure I get your comment. I want to be clear on responsibilities of the facets and responsibility of the Graph.
Assume we have a SpellIntFacet that is calculating the values you want.
There are a few ways removal can happen.
(1) Removal can be structural. This is true of REMOVE, and also HITDIE (Hit Die Locking). These structural changes are handled by the Graph (which then has some method of triggering updates in the facets, as per #4 from my initial note in this thread). SpellIntFacet just queries what is in the graph and all is well.
(2) Removal can be algorithmic. I can't name an exact use like this off the top of my head, but the HANDS override in Templates (vs. set in Race) is a close analogy. For a remove case, one example is that we could have a "SUPPRESSINTBONUS:TRUE" token in a Template LST file. This would be locally detected by the SpellIntFacet to control the algorithm. However, that would mean the SpellIntFacet would have to subscribe to the TemplateFacet. This creates a new linkage & thus may force more cache updates when Templates are added to a PC, but it does not influence the local/global nature of a cache.
(3) Removal can be BONUS based. In that case, a template removing all Spell INT bonuses would trigger some form of removal by negative BONUS objects. There would be a BonusFacet that would process BONUS totals, and that BonusFacet would be connected to the SpellIntFacet. Therefore, the BONUS facet is what is responsible for tracking (and probably caching) BONUS values.
Does that help clarify?
I list those because I don't see any of them really impacting the local/global nature of the cache (which is why I'm concerned I don't get what you're trying to say); however, they DO result in different required "subscriptions" by Facets (this is why getting the Facets connected is so important)
> > 3) How does the HandsFacet get connected? Presumably it needs to
> > know about the RaceFacet and TemplateFacet. Presumably this is
> > provided at construction or in setters or ??. Thoughts? (one
> > comment: During construction concerns me because we may run into
> > circular dependencies)
> > This gets complicated (and I haven't got an answer), we're going to have to try and make assumptions about what can know about what.
It's not assumptions, it will be rigidly defined. The problem is that it is not a directed acyclic graph. It's cyclic, which means it's nasty. It's also a lot of connections, so will take a bunch of code to do all of the facet initialization.
> Since so many rule systems like to have strange an unusual rules we could start drifting back towards the 'everything' knows about 'everything' PObject model, which is less than ideal :|
I'm not concerned about this. The point of generating a modular system is to be able to handle these situations with a new module (or facet in our case). There are at least 2 decent ways of handling that, but I don't want to have that implementation detail on the table right now, for fear of debate that is distracting to our immediate concerns (IMHO anyway). Andrew, can you capture this as an action of unfinished discussions on the list you have on the Wiki?
> > 4C) Fine grained updates, where explicit change messages are
> > transmitted through a Listener-Event system (or something similar)
> > between the facets.
> > So Facets listening to 'their' nodes on the Graph? That's a valid option as well in my book.
Not sure what you mean by 'their', so let me clarify: The HandsFacet would "subscribe" to the RaceFacet and the TemplateFacet and thus get changes if the Race is changed or a Template is added or removed from the PC. If you add the "Dodge" feat, there is no work for the HandsFacet to do (it will not receive an event). This fine grained update is much more CPU friendly since it will not waste effort for "immaterial" changes. It also doesn't require a global "isDirty" system, which is subject to mistakes if it is forgotten (or causes false positives on changed PCs if used in places where it is not necessary).
This is my preferred method.
> I use Spring a bit at work, and there are other DI and AOP frameworks out there, but as you say I'd like to see concrete examples thought out using those before we made a switch over.
The primary use case is for the structural connecting of the facets (primarily to avoid a multi-hundred line constructor of PlayerCharacter that is constructing facets and connecting them). This is very open as to whether it is worth the cost of bringing in a framework like Tapestry or Spring. I think the tipping point will be in testing (the frameworks may be able to provide an improved testing environment) and/or once we go beyond d20. At this point, I don't think we have any AOP use cases.
TP.