Difference between revisions of "Rules Data Store"

From PCGen Wiki
Jump to: navigation, search
(Characteristics/Weaknesses of the existing system)
 
(One intermediate revision by the same user not shown)
Line 3: Line 3:
 
   |}
 
   |}
  
==Background==
+
=Background=
  
This document is primarily intended to communicate the design of PCGen Rules Data Store.  See the Overall System Figure [[Image:Overall_system_figure.png|frame|Block diagram of proposed CDOM structure]] to get an understanding of the place of the Rules Data Store within the entire PCGen code base and architecture. 
+
This document is primarily intended to communicate the design of PCGen Rules Data Store.   
  
 
This document provides a detailed overview of the architecture of a specific portion of PCGen.  The overall architecture and further details of other subsystems and processes are provided in separate documents available on the [[Architecture]] page.
 
This document provides a detailed overview of the architecture of a specific portion of PCGen.  The overall architecture and further details of other subsystems and processes are provided in separate documents available on the [[Architecture]] page.
  
==Overview==
+
=Overview=
  
The Rules Data Store is one of the major components of PCGen.  It is responsible for storing information about game systems.  As a "Data Store", it is very much akin to a complicated database (it could be converted into an actual database with minor effort).  The Rules Data Store is not designed to have methods that interpret the contents of the Rules Data Store, nor is the Rules Data Store capable of storing the information it contains into a persistent state.  The conversion to and from a persistent state is owned by the [[Rules Persistence System]]
+
The Rules Data Store is one of the major components of PCGen.  It is responsible for storing information about game systems.  As a "Data Store", it is very much akin to a complicated database (it could be converted into an actual database with some effort).  The Rules Data Store is not designed to have methods that interpret the contents of the Rules Data Store, nor is the Rules Data Store capable of storing the information it contains into a persistent state.  The conversion to and from a persistent state is owned by the [[Rules Persistence System]].
  
==Additional Requirements==
+
=Requirements=
  
In addition to the foundation [[Design Concepts for PCGen]], the following additional structural requirements are applied to the Rules Data Store
+
==Flexible Data Structure==
 
 
 
 
 
 
===Minimize Fixed Knowledge===
 
  
 
Information should be stored in a fashion that minimizes fixed data structures, including,
 
Information should be stored in a fashion that minimizes fixed data structures, including,
 
but not limited to, fixed field names within CDOM Object implementations.
 
but not limited to, fixed field names within CDOM Object implementations.
  
<b>Basis:</b> Fixed data structures drive code changes when additional features are added to PCGen.
+
Fixed data structures drive code changes when additional features are added to PCGen.
 
The end design goal should allow for new features to be added to PCGen entirely  
 
The end design goal should allow for new features to be added to PCGen entirely  
through plugins, without modification of the core.  This means the Rules Data Store must store
+
through plugins/data, without modification of the core.  This means the Rules Data Store must store
 
data in a fashion that does not fix or limit what information can be stored within  
 
data in a fashion that does not fix or limit what information can be stored within  
 
the Rules Data Store.
 
the Rules Data Store.
  
===Separate Static and Dynamic data===
+
==Separate Static and Dynamic data==
  
 
Information about a CDOM Object should be separate from information about how the
 
Information about a CDOM Object should be separate from information about how the
 
object affects a Player Character.
 
object affects a Player Character.
  
<b>Basis:</b> Storing both stable and dynamic information within the same object means
+
Storing both stable and dynamic information within the same object means
 
the entire object must be cloned in order to be re-used.  This results in a waste
 
the entire object must be cloned in order to be re-used.  This results in a waste
 
of resources (duplicate information) which can be eliminated if a CDOM Object does
 
of resources (duplicate information) which can be eliminated if a CDOM Object does
Line 42: Line 38:
 
PlayerCharacter.
 
PlayerCharacter.
  
==Sub-components==
+
=Sub-components=
  
===CDOM Objects===
+
==CDOM Objects==
  
 
CDOM Objects are the primary component of the Rules Data Store.  They store information about the impact
 
CDOM Objects are the primary component of the Rules Data Store.  They store information about the impact
 
to a Player Character and other relationships that the CDOM Object has within PCGen.
 
to a Player Character and other relationships that the CDOM Object has within PCGen.
  
===Reference Context===
+
==Reference Context==
  
 
The Reference Context is the indexing system used to determine what objects exist within the
 
The Reference Context is the indexing system used to determine what objects exist within the
Line 56: Line 52:
 
to by a specific key.
 
to by a specific key.
  
===Master List Interface===
+
==Master List Interface==
  
 
The Master List Interface is used to index the initial contents of "global" CDOMLists.   
 
The Master List Interface is used to index the initial contents of "global" CDOMLists.   
Line 62: Line 58:
 
the contents of the CLASSES token within Spell LST files.
 
the contents of the CLASSES token within Spell LST files.
  
===Helpers===
+
==Helpers==
  
 
Helpers are objects that are designed to be stored in CDOM Objects.  These objects store information
 
Helpers are objects that are designed to be stored in CDOM Objects.  These objects store information
Line 69: Line 65:
 
information.
 
information.
  
===Content===
+
==Content==
  
 
Content are objects that are more complex information that can be provided to a PlayerCharacter.
 
Content are objects that are more complex information that can be provided to a PlayerCharacter.
Line 80: Line 76:
 
objects, in which case Content could be granted and Helpers could not.
 
objects, in which case Content could be granted and Helpers could not.
  
===Modifiers===
+
=Key Design Decisions=
 
 
Modifiers are objects capable of altering objects of a given type (typically Helpers or Content).
 
Modifiers may be fixed replacement Modifiers (always provide a specific value), or only act under
 
a limited set of circumstances specific to a given Player Character.
 
 
 
Hit Die Locks are a good example of a Modifier (of HitDie objects).
 
 
 
==Key Design Decisions==
 
  
===Value Semantic Data Structure===
+
==Value Semantic Data Structure==
  
 
The Rules Data Store will be a Value-Semantic data structure, in order to protect the
 
The Rules Data Store will be a Value-Semantic data structure, in order to protect the
 
contents of the Rules Data Store from unintended modification.   
 
contents of the Rules Data Store from unintended modification.   
  
<b>Underlying Requirement(s):</b> [[Design_Concepts_for_PCGen#Data Encapsulation|Data Encapsulation]]
+
First, this avoids confusion.  Reference-Semantic structures allow internal
 
 
<b>Basis:</b> First, this avoids confusion.  Reference-Semantic structures allow internal
 
 
contents to be extracted via a "get" method and then the internal structure of the  
 
contents to be extracted via a "get" method and then the internal structure of the  
 
object can be modified.  This is considered by some a violation of object-oriented
 
object can be modified.  This is considered by some a violation of object-oriented
Line 103: Line 89:
 
"get" and not "get in order to set".
 
"get" and not "get in order to set".
  
Second, in restricting the design, this minimizes the change for unintended  
+
Second, in restricting the design, this minimizes the change for unintended consequences.  Accidental modification of a data structure that should not be changed is possible in reference semantic systems. It is, by definition, impossible in value semantic systems.
consequences.  Accidental modification of a data structure that should not be  
 
changed is possible in reference semantic systems. It is, by definition, impossible
 
in value semantic systems.
 
 
 
More information on semantics and object ownership can be found in [http://www.ibm.com/developerworks/java/library/j-jtp06243.html Whose Object is it Anyway?]
 
 
 
<b>Implementation:</b> CDOMObject will not allow any of its internal data to be modified by
 
any means other than through a method called on CDOMObject.  There are some
 
items stored in lists in the CDOMObject, and those lists will be copied
 
before they are returned to the calling method.  The consequence of this
 
is that any modification to the returned list will NOT impact the
 
CDOMObject.  Thus, there is never a need to make a defensive copy of any
 
Collection returned by CDOMObject.
 
  
===CDOMObject stores information in maps based on keys===
+
Specifically, CDOMObject will not allow any of its internal data to be modified by any means other than through a method called on CDOMObject.  There are some items stored in lists in the CDOMObject, and those lists will be copied before they are returned to the calling method.  The consequence of this is that any modification to the returned list will NOT impact the CDOMObject.  Thus, there is never a need to make a defensive copy of any Collection returned by CDOMObject.
  
CDOMObject will store information indirectly in Maps, with keys used
+
==CDOMObject stores information in maps based on keys==
to index the information stored within the CDOMObject.
 
  
<b>Underlying Requirement(s):</b> [[Rules Data Store#Minimize Fixed Knowledge|Minimize Fixed Knowledge]], [[Design_Concepts_for_PCGen#Data Encapsulation|Data Encapsulation]], [[Design_Concepts_for_PCGen#Minimize Process.2FStructural Models|Minimize Process/Structural Models]], [[Design_Concepts_for_PCGen#Increased Flexibility|Increased Flexibility]]
+
CDOMObject will store information indirectly in Maps, with keys used to index the information stored within the CDOMObject.
  
<b>Basis:</b> This minimizes the number of fields within CDOMObject to less than
+
This minimizes the number of fields within CDOMObject to less than ten.  This helps to minimize the size of the code that has to be considered when evaluating changes.  This also provides tremendous code reuse, as there are a limited number of methods used to access data in a CDOMObject.
ten.  This helps to minimize the size of the code that has to be considered
 
when evaluating changes.  This also provides tremendous code reuse, as there  
 
are a limited number of methods used to access data in a CDOMObject.
 
  
This also eliminates almost all fixed knowledge within CDOMObjects.  Since
+
This also eliminates almost all fixed knowledge within CDOMObjects.  Since the information is stored in a key-value pair, the CDOMObject class and derivaties don't require changes when new keys (and thus new behavior) are defined and added to PCGen.
the information is stored in a key-value pair,  
 
the CDOMObject class and derivaties don't require changes  
 
when new keys (and thus new behavior) are defined and added to
 
PCGen
 
  
<b>Implementation:</b> There are two important components to the storage of information in maps
+
There are two important components to the storage of information in maps within the CDOMObject.  The first is the maps themselves.  There are individual maps for different types of objects, including Integers, Strings, Formulas, Variables, and Lists.  There is also a "catch all" Object map.
within the CDOMObject.  The first is the maps themselves.  There are individual maps
 
for different types of objects, including Integers, Strings, Formulas, Variables,  
 
and Lists.  There is also a "catch all" Object map.
 
  
 
Each of these maps has an associated enumeration serving as the keys to the map.
 
Each of these maps has an associated enumeration serving as the keys to the map.
Line 153: Line 115:
 
a single file (the enumeration class file).
 
a single file (the enumeration class file).
  
===CDOMLists do not contain objects===
+
==CDOMLists do not contain objects==
  
 
CDOMLists do not contain CDOMObjects.  Rather they are an identifier used to
 
CDOMLists do not contain CDOMObjects.  Rather they are an identifier used to
Line 159: Line 121:
 
a given PlayerCharacter must be stored independently of the CDOMList.
 
a given PlayerCharacter must be stored independently of the CDOMList.
  
<b>Underlying Requirement(s):</b> [[Rules Data Store#Separate Static and Dynamic data|Separate Static and Dynamic data]]
+
Lists of CDOMObjects (such as Spell Lists and Skill Lists) may be modified
 
 
<b>Basis:</b> Lists of CDOMObjects (such as Spell Lists and Skill Lists) may be modified
 
 
by tokens contained within CDOMObjects added to a PlayerCharacter.  An Ability may
 
by tokens contained within CDOMObjects added to a PlayerCharacter.  An Ability may
 
allow a specific Spell to be added to the Spell List of a Class, for example.  In
 
allow a specific Spell to be added to the Spell List of a Class, for example.  In
Line 168: Line 128:
 
it must be an identifier to the list of objects.
 
it must be an identifier to the list of objects.
  
<b>Implementation:</b> A Master List Interface is used to store global lists (such as Class Spell
+
A Master List Interface is used to store global lists (such as Class Spell
 
Lists).  Modifications to those Master Lists (or to other lists that are built  
 
Lists).  Modifications to those Master Lists (or to other lists that are built  
 
dynamically as a Player Character is generated) can be stored within CDOMObjects.
 
dynamically as a Player Character is generated) can be stored within CDOMObjects.
Line 178: Line 138:
 
associations.)
 
associations.)
  
===Class Levels are separate objects===
+
==Class Levels are separate objects==
  
 
Class Levels are separate objects from the Class object.
 
Class Levels are separate objects from the Class object.
  
<b>Underlying Requirement(s):</b> [[Design_Concepts_for_PCGen#Data Encapsulation|Data Encapsulation]], [[Design_Concepts_for_PCGen#Avoid Contracts|Avoid Contracts]]
+
This is primarily done in order to simplify management of class levels.   
 
 
<b>Basis:</b>  This is primarily done in order to simplify management of class levels.   
 
 
Substitution classes (Which replace class level behavior) are easily implemented in  
 
Substitution classes (Which replace class level behavior) are easily implemented in  
 
a system that stores class levels as separate objects.  In addition, this use of
 
a system that stores class levels as separate objects.  In addition, this use of
Line 191: Line 149:
 
an entirely new class level can be created)
 
an entirely new class level can be created)
  
<b>Implementation:</b> Class levels are separate objects, but are stored within the PCClass.
+
Class levels are separate objects, but are stored within the PCClass.
  
===Equipment Heads are distinct objects===
+
==Equipment Heads are distinct objects==
  
 
Equipment heads are stored as distinct objects from the Equipment.
 
Equipment heads are stored as distinct objects from the Equipment.
  
<b>Underlying Requirement(s):</b> [[Rules Data Store#Minimize Fixed Knowledge|Minimize Fixed Knowledge]], [[Design_Concepts_for_PCGen#Increased Flexibility|Increased Flexibility]]
+
The current Rules Persistence System assumes that a piece of  
 
 
<b>Basis:</b> The current Rules Persistence System assumes that a piece of  
 
 
Equipment can have only two heads, but this is an arbitrary limitation.
 
Equipment can have only two heads, but this is an arbitrary limitation.
 
It also causes code duplication when primary and alternative methods are  
 
It also causes code duplication when primary and alternative methods are  
 
required in order to query information out of the Equipment.
 
required in order to query information out of the Equipment.
  
<b>Implementation:</b> EquipmentHead is now a separate CDOMObject used to store information
+
EquipmentHead is now a separate CDOMObject used to store information
 
that is specific to a specific "head" (such as damage, critical hit range, etc.).  
 
that is specific to a specific "head" (such as damage, critical hit range, etc.).  
 
The EquipmentHead is known to (and stored in) the Equipment.
 
The EquipmentHead is known to (and stored in) the Equipment.

Latest revision as of 22:08, 25 February 2018

Background

This document is primarily intended to communicate the design of PCGen Rules Data Store.

This document provides a detailed overview of the architecture of a specific portion of PCGen. The overall architecture and further details of other subsystems and processes are provided in separate documents available on the Architecture page.

Overview

The Rules Data Store is one of the major components of PCGen. It is responsible for storing information about game systems. As a "Data Store", it is very much akin to a complicated database (it could be converted into an actual database with some effort). The Rules Data Store is not designed to have methods that interpret the contents of the Rules Data Store, nor is the Rules Data Store capable of storing the information it contains into a persistent state. The conversion to and from a persistent state is owned by the Rules Persistence System.

Requirements

Flexible Data Structure

Information should be stored in a fashion that minimizes fixed data structures, including, but not limited to, fixed field names within CDOM Object implementations.

Fixed data structures drive code changes when additional features are added to PCGen. The end design goal should allow for new features to be added to PCGen entirely through plugins/data, without modification of the core. This means the Rules Data Store must store data in a fashion that does not fix or limit what information can be stored within the Rules Data Store.

Separate Static and Dynamic data

Information about a CDOM Object should be separate from information about how the object affects a Player Character.

Storing both stable and dynamic information within the same object means the entire object must be cloned in order to be re-used. This results in a waste of resources (duplicate information) which can be eliminated if a CDOM Object does not store dynamic information. Implementing this structural requirement will mean CDOM Objects will not need to be cloned in order to be placed within a PlayerCharacter.

Sub-components

CDOM Objects

CDOM Objects are the primary component of the Rules Data Store. They store information about the impact to a Player Character and other relationships that the CDOM Object has within PCGen.

Reference Context

The Reference Context is the indexing system used to determine what objects exist within the Rules Data Store. For purposes of the Rules Data Store, the Reference Context is capable of returning all of the objects of a given type (e.g. Language), or an object of a given type that is referred to by a specific key.

Master List Interface

The Master List Interface is used to index the initial contents of "global" CDOMLists. These global lists include things like ClassSpellLists, which are initialized by the contents of the CLASSES token within Spell LST files.

Helpers

Helpers are objects that are designed to be stored in CDOM Objects. These objects store information in a type-safe fashion, and often provide useful methods around the information contained within the Helper. Helpers are generally very simple objects to store a very small group of closely related information.

Content

Content are objects that are more complex information that can be provided to a PlayerCharacter. These objects store information in a type-safe fashion, and often provide useful methods around the information contained within the Content. Content objects may also have Prerequisites that a Player Character must pass before the Content can be used by the Player Character.

It is noted that the distinction between Helpers and Content in PCGen 5.16 is extremely weak. The reason for the distinction is future versions of PCGen may use take up the concept of "granting" objects, in which case Content could be granted and Helpers could not.

Key Design Decisions

Value Semantic Data Structure

The Rules Data Store will be a Value-Semantic data structure, in order to protect the contents of the Rules Data Store from unintended modification.

First, this avoids confusion. Reference-Semantic structures allow internal contents to be extracted via a "get" method and then the internal structure of the object can be modified. This is considered by some a violation of object-oriented design, and can be highly confusing if a developer expects a "get" to really mean "get" and not "get in order to set".

Second, in restricting the design, this minimizes the change for unintended consequences. Accidental modification of a data structure that should not be changed is possible in reference semantic systems. It is, by definition, impossible in value semantic systems.

Specifically, CDOMObject will not allow any of its internal data to be modified by any means other than through a method called on CDOMObject. There are some items stored in lists in the CDOMObject, and those lists will be copied before they are returned to the calling method. The consequence of this is that any modification to the returned list will NOT impact the CDOMObject. Thus, there is never a need to make a defensive copy of any Collection returned by CDOMObject.

CDOMObject stores information in maps based on keys

CDOMObject will store information indirectly in Maps, with keys used to index the information stored within the CDOMObject.

This minimizes the number of fields within CDOMObject to less than ten. This helps to minimize the size of the code that has to be considered when evaluating changes. This also provides tremendous code reuse, as there are a limited number of methods used to access data in a CDOMObject.

This also eliminates almost all fixed knowledge within CDOMObjects. Since the information is stored in a key-value pair, the CDOMObject class and derivaties don't require changes when new keys (and thus new behavior) are defined and added to PCGen.

There are two important components to the storage of information in maps within the CDOMObject. The first is the maps themselves. There are individual maps for different types of objects, including Integers, Strings, Formulas, Variables, and Lists. There is also a "catch all" Object map.

Each of these maps has an associated enumeration serving as the keys to the map. These enumerations are found in pcgen.cdom.enumeration.

Some of these keys are defined in the enumeration class to have default values. This is especially valuable for Integers, Formulas, and Objects (specifically when the Object is a Boolean). Using the getSafe methods within CDOMObject allows a calling method to get either the value set for the given key within the CDOMObject, or if there is no defined value for the given key, then the default value defined in the enumeration is returned. As a side effect, the default values for all of the keys of a given type are available within a single file (the enumeration class file).

CDOMLists do not contain objects

CDOMLists do not contain CDOMObjects. Rather they are an identifier used to identify a list of objects. The CDOMObjects contained within the CDOMList for a given PlayerCharacter must be stored independently of the CDOMList.

Lists of CDOMObjects (such as Spell Lists and Skill Lists) may be modified by tokens contained within CDOMObjects added to a PlayerCharacter. An Ability may allow a specific Spell to be added to the Spell List of a Class, for example. In order to allow this dynamic modification of lists while avoiding the storage of redundant information, a CDOMList may not contain the objects in the list; rather, it must be an identifier to the list of objects.

A Master List Interface is used to store global lists (such as Class Spell Lists). Modifications to those Master Lists (or to other lists that are built dynamically as a Player Character is generated) can be stored within CDOMObjects. These list modifications are indexed by the CDOMList object identifying the list to be modified. Specific associations to the list (such as spell level or skill cost) are stored as a target with the CDOMObject. (The list modifications are stored as a two key map: The first key is the CDOMList, the second key is the CDOMObject(s) to be added to the list, the target of the map is a list of associations.)

Class Levels are separate objects

Class Levels are separate objects from the Class object.

This is primarily done in order to simplify management of class levels. Substitution classes (Which replace class level behavior) are easily implemented in a system that stores class levels as separate objects. In addition, this use of a separate objects avoids contracts in the addition of variables to the Class Level (as individual variables don't need to be cleared for substitution classes, an entirely new class level can be created)

Class levels are separate objects, but are stored within the PCClass.

Equipment Heads are distinct objects

Equipment heads are stored as distinct objects from the Equipment.

The current Rules Persistence System assumes that a piece of Equipment can have only two heads, but this is an arbitrary limitation. It also causes code duplication when primary and alternative methods are required in order to query information out of the Equipment.

EquipmentHead is now a separate CDOMObject used to store information that is specific to a specific "head" (such as damage, critical hit range, etc.). The EquipmentHead is known to (and stored in) the Equipment.

Characteristics/Weaknesses of the existing system

  1. Value semantic systems can suffer a performance penalty, because items like lists must be copied before they are returned by a "get" method on a value-semantic object. The initial design for the Rules Data Store is a fully value-semantic Rules Data Store, Any specific performance isuses once the Rules Data Store is fully implemented.
  2. In PCGen 5.16, the enumeration classes require modification to add a new key. However, adding the capability to define new keys dynamically is likely to be added to a future version of PCGen.
  3. The CDOMObject stores information in maps based on keys design choice has a mixed effect on memory usage. In PCGen 5.16, all of the maps are constructed, even if they are empty. This provides a memory overhead that may be removed by using lazy instantiation in a future version of PCGen.
  4. The ReferenceContext serves both the Rules Data Store and the Rules Persistence System, and we should probably break out this behavior of Reference Context from the behavior in the Rules Persistence System. It may be confusing to have two functions using the same name, especially as this one is intended to be much more limited than the Reference Context behavior in the Rules Persistence System. This may simply be done by having the Reference Context implement a read-only interface designed to be used at runtime.
  5. Depending on the ReferenceContext naming above, The Master List Interface may need a different name.