Difference between revisions of "Design Concepts for PCGen"

From PCGen Wiki
Jump to: navigation, search
 
Line 3: Line 3:
 
   |}
 
   |}
  
==Functional Requirements==
+
In general, there are a number of key considerations that are driving the code decisions and architecture of PCGen.
  
The following functional requirements are provided for use in understanding the basis for the PCGen architecture. Functional requirements are constraints on features as they appear to a user of PCGen.
+
=Subsystem Isolation=
 
+
Overall, we want the subsystems (loader/core/output) to be sufficiently independent of each other that they don't interact except through a well-defined API and also so they only operate at the appropriate times...  Meaning the once load is complete, the loader system should not need to be called againAlso, output should be called during output and not during regular character processing.   
===Compatibility with Previous Versions===
+
Unfortunately, both of these are not true with the existing systems... it is possible to write a token that both uses items from the output tokens as well as is parsed at runtime - meaning all of the systems are intertwined today.  The strategic designs that will prevent that interaction are described below.
 
 
A version of PCGen must be fully capable of loading LST data files that were compatible with the previous release. Any tokens that were deprecated in the previous revision may be removed.  For example: PCGen 5.16 must be capable of fully loading PCGen 5.14 LST data files.  Data from older 5.x releases (in particular PCGen 5.12 and 5.10) may be compatible with PCGen 5.16; however, there are known ambiguities that prevent 100% compatibility with older releases. 
 
 
 
With few exceptions, this requirement must be met.  Other features of the system (requirements and other good design guidelines) will be sacrificed to meet this requirement. Exceptions to this requirement require unique conversion scripts (which may prompt the user to resolve ambiguity) to be available in the LST Converter.
 
 
 
All tokens deprecated in a given release of PCGen should have automatic conversion using the LST Converter if there is equivalent function in the new version.  To remove function from PCGen requires explicit approval from the [[Content]] team
 
 
 
<b>Basis:</b> There is a tremendous investment in the PCGen code, data and documentation.  This compatibility requirement ensures the ability to leverage that time investment, especially in data and documentation.
 
 
 
===Increased Flexibility===
 
 
 
Eliminating hard coded values and special cases that currently exist in the PCGen code base will allow PCGen to more easily support non-d20 systems.  In addition, increased flexibility will provide for faster feature enhancement, providing additional benefit to users.
 
 
 
<b>Basis:</b> Desire for faster turnover of feature requests, and long-term strategy to expand the PCGen universe to include non-d20 based game systems to increase function for existing users and to attract new users to PCGen.
 
 
 
==Structural Requirements==
 
 
 
The following structural requirements are provided for use in understanding the basis for the PCGen architecture.  Structural requirements are constraints on features as they appear to a developer of PCGen.
 
 
 
Note: It is recognized that some of these items would qualify more as "design" than "architecture", as they are general features or characteristics of well-written software systems.  Without any disrespect for software architecture purists, we include a number of those design characteristics, as they help to contrast the current PCGen architecture from architecture of earlier versions of PCGen.
 
 
 
===Minimize Process/Structural Models===
 
 
 
PCGen should have a minimal set of design structures used to specify the functions required to build a Player Character.
 
 
 
<b>Basis:</b> This minimizes the number of mental models a developer must understand. Reduced quantity of design patterns and structures improves the ability of new (and existing!) developers to understand the code. This also allows greater code reuse and reduces code duplication (which is subject to copy/paste error)Selection of appropriate models will also reduce the number of exceptions in the code, eliminating further risk of bugs and confusion for developers.
 
 
 
===Information Hiding===
 
 
 
The format of data files on disk should be independent of the processing of a game system or Player Character.
 
 
 
<b>Basis:</b> This insulates the code (modifying a player character or the game system data) from changes in the data file format.  This increases the flexibility to add features to PCGen without core changesThis facilitates unit testing by improving component isolation.
 
 
 
===Data Encapsulation===
 
 
 
There should be defined and limited interfaces between modules of PCGen.
 
 
 
<b>Basis:</b> This improves code maintainability.  This truly insulates modules of PCGen from changes elsewhere in the system.  This therefore facilitates parallel developmentThis also improves the ability to unit test the code, as "mock" objects that implement the framework can be used for testing.
 
 
 
===Stable Code Structure===
 
 
 
Dependency between packages and classes will result in a Directed Acyclic Graph.
 
 
 
<b>Basis:</b> The PCGen code base is over 2,000 classes.  This is a significant code base and requires isoloating subsystems and defining dependencies in order to minimize the impact of code changes.  Improved code structure also facilitates testing.  Eliminating tangles in Class dependency will improve the ability to write true unit tests (tests that work on a single Class).  This means it will be possible to catch smaller errors due to incorrect modifications of the PCGen code base.  Improved structure also facilitates understanding of the code by developers.  The overall impact of good code structure is seen to both developers and end users as improved speed and ability to modify the PCGen code.
 
 
 
For further information on why this is important, you can read more about [http://www.objectmentor.com/resources/articles/granularity.pdf granularity] at ObjectMentor
 
 
 
===Avoid Contracts===
 
 
 
Two forms of contracts should be avoided: (1) When a developer makes a code modification, the developer should not be forced to make a matching modification in another location in the code. (2) When a change is made to the internal data structure, a significant amount of "reorganization" to ensure a valid data structure should not be necessary.
 
 
 
<b>Basis:</b> Contracts cause problems because they introduce bugs into software when matching changes are not made.  They also make it more difficult for developers to understand the architecture of a system, because they are forced to focus on adhering to the contracts. Data structure contracts can result in invalid data structures, and often lead to performance issues as the data structure is validated and corrected.
 
 
 
===Minimize Order Dependency===
 
 
 
The number of order dependent operations should be minimized.
 
 
 
<b>Basis:</b> Order dependency can cause significant issues, especially as it is hard to maintain accurate documentation of such restrictions.  Operations that are not order dependent can also be parallelized (e.g. on multi-processor systems) to improve performance.
 
 
 
 
 
==Key Design Decisions==
 
 
 
===Data Persistence Interface===
 
 
 
The Data Persistence format must be independent of internal data structure. (The internal data structure must not have
 
knowledge of the data persistence file format)
 
 
 
<b>Underlying Requirement(s):</b> [[Design_Concepts_for_PCGen#Information Hiding|Information Hiding]]
 
 
 
<b>Basis:</b> This abstracts data persistence from the internal data structure.  It forces the entire persistence contents to
 
be parsed on data load.  This ensures any errors in data files are caught at data load, rather than at runtime.
 
 
 
===The Persistence System IO===
 
 
 
The input and output of data persistence information should be an integral part of the data persistence system.
 
 
 
<b>Underlying Requirement(s):</b> [[Design_Concepts_for_PCGen#Data Encapsulation|Data Encapsulation]], [[Design_Concepts_for_PCGen#Information Hiding|Information Hiding]]
 
 
 
<b>Basis:</b> Adding output to the persistence system provides the ability to reuse the data persistence system in a data
 
file editor, as well as the runtime system.  This sharing of code helps to guarantee the integrity of the data file
 
editorSuch a structure also facilitates unit testing, as the persistence system can be tested independently of
 
the core code.
 
 
 
===Character Persistence Interface===
 
 
 
The Character Persistence format must be independent of the core code and data structure. (The internal PC data
 
structure must not have knowledge of the PC persistence file format)
 
 
 
<b>Underlying Requirement(s):</b> [[Design_Concepts_for_PCGen#Information Hiding|Information Hiding]]
 
 
 
<b>Basis:</b> This abstracts character persistence from the internal data structure.  This also implies and ensures that
 
when a character is saved, it can be restored, even independent of the original persistent data being available.
 
 
 
===Catch Errors Early===
 
  
 +
=Catch Errors Early=
 
Errors in the data files should be caught during data file load, and should not trigger runtime errors.
 
Errors in the data files should be caught during data file load, and should not trigger runtime errors.
 
<b>Underlying Requirement(s):</b> [[Design_Concepts_for_PCGen#Information Hiding|Information Hiding]]
 
 
<b>Basis:</b> Given data persistence being independent of the internal data structure, all references will be resolved at
 
load time.  This will ensure that all objects in a given namespace possess a unique KEY, regardless of the source file.
 
Also, all object references can be validated to ensure an object that was actually constructed and loaded.
 
  
===Shared Persistence System with Editor===
+
=Eliminate Hardcoding=
 +
Eliminating hard coded values and special cases that currently exist in the PCGen code base will allow PCGen to more easily support our existing systems and non-d20 systems.  The side effect here is an increasingly data-driven design.
  
The data persistence system should be usable for both a data file editor and the runtime character generation program.
+
=Order of operations clarity=
 +
There are two order of operations items we are trying to address
  
<b>Underlying Requirement(s):</b> Code Reuse (general design characteristic)
+
==In Data==
 +
Right now, for a token like REACH, there is an order of operations ambiguity - what Template is applied is not exactly clear.  This is one example of many in the system.  The new formula system handles this one with PRIORITY=x. 
  
<b>Basis:</b> A significant investment made in ensuring that persistent data is read without errors should be reused across
+
==In Code==
both a data file editor and the runtime system.  This reduces the risk of error, ensures that the editor will always
+
Effectively there are certain things that must happen "first" - except in many cases, there are loops or other conditions that mean we need designs and technologies that overcome those "reference before constructed" situations.
be up to date (a problem in PCGen 5.x) and provides additional editing capabilities (e.g. edit data in place) that are
 
not available in PCGen 5.x.
 

Latest revision as of 20:07, 25 February 2018

In general, there are a number of key considerations that are driving the code decisions and architecture of PCGen.

Subsystem Isolation

Overall, we want the subsystems (loader/core/output) to be sufficiently independent of each other that they don't interact except through a well-defined API and also so they only operate at the appropriate times... Meaning the once load is complete, the loader system should not need to be called again. Also, output should be called during output and not during regular character processing. Unfortunately, both of these are not true with the existing systems... it is possible to write a token that both uses items from the output tokens as well as is parsed at runtime - meaning all of the systems are intertwined today. The strategic designs that will prevent that interaction are described below.

Catch Errors Early

Errors in the data files should be caught during data file load, and should not trigger runtime errors.

Eliminate Hardcoding

Eliminating hard coded values and special cases that currently exist in the PCGen code base will allow PCGen to more easily support our existing systems and non-d20 systems. The side effect here is an increasingly data-driven design.

Order of operations clarity

There are two order of operations items we are trying to address

In Data

Right now, for a token like REACH, there is an order of operations ambiguity - what Template is applied is not exactly clear. This is one example of many in the system. The new formula system handles this one with PRIORITY=x.

In Code

Effectively there are certain things that must happen "first" - except in many cases, there are loops or other conditions that mean we need designs and technologies that overcome those "reference before constructed" situations.