Thoughts on architecture for the GDA backend

Phil Longstaff plongstaff at rogers.com
Mon Dec 17 16:40:54 EST 2007


   Derek Atkins wrote:

Hi,

Phil Longstaff [1]<plongstaff at rogers.com> writes:


Except for a number of bugs (and a lot of testing, and a load/save UI),
the GDA backend basically works for the objects outside of the business
objects.  I also want to add an audit trail for changes and version
support to detect when a db needs to be updated to a newer version.

So we've reached feature-parity with the 1.6 Postgres backend?
Excellent!  Definitely good progress.  What's the time frame to get
the business objects done?


   Depends, of course, on how much time I can spend on the project.  With
   holidays coming up, I should be able to spend more time, and maybe get
   the business objects done.  I've never used them before, so there will
   be a bit of a learning curve.


Some thoughts:
- the GDA backend pulls the data from the engine objects and builds an
INSERT/UPDATE query using the values.  This requires the backend to know
what values/types need to be persistent.

In the current GnuCash architecture this is done by having the
backend provide a framework and then having "per-backend object
plugins" that define this persistence.


- create a new GObject interface which has methods for 1) getting a
dictionary of persistent data for the object 2) getting/setting
persistent data.  The goal would be to have the engine object and its
class have a bigger role in defining the db table columns in order to
better encapsulate persistence information in the engine objects.  The
backend would then be required to transfer the persistence information
for an object to/from the db or file.

Thoughts?

Do we really need this?  Is the current plug-in framework not
sufficient?  Or do you really believe that you can come up
with an interface that is backend agnostic?  I'd like to see
a design proposal before going along this route, because if it's
not backend agnostic then it's no better than what we currently
have.

   I'm thinking of something like a modified version of the memento design
   pattern ([2]http://en.wikipedia.org/wiki/Memento_pattern).  It may have
   originally been designed to allow state modifications to be undone, but
   it should also be usable here with the gnucash object being the object
   whose state needs to be saved and the backend being the caretaker.
   However, we wouldn't need an object to be the memento.  We *would* need
   name/type information to allow the memento state info to be
   saved/restored.
   In one sense, if every object kept made all of its information
   available via kvp, it would be easy to store since there is a flexible
   mechanism there, and there is no maintenance problem keeping the
   backend up-to-date with the schema.
   Take the account object as an example.
   The XML backend calls xaccAccountGetName(), xaccAccountGetCommodity(),
   ... and then encodes each piece of information.  The GDA backend calls
   the same functions, formats the SQL INSERT or UPDATE request and passes
   it to the db to be executed and save the object.  If a new attribute is
   added to the account engine object, each backend needs to be modified
   to call a new function to get the attribute value, then each backend
   needs to encode it properly in order to save it.
   The Account engine object now has GObject properties defined for all of
   its internal attributes.  This allows g_object_get() and g_object_set()
   to be called to get/set attribute values respectively, but also allows
   g_object_class_list_properties() to be called to get a list of the
   attributes including type information.  A backend could call
   g_object_class_list_properties() and then, for each attribute, call
   g_object_get(), encode the value and save it.  It would need to to know
   how to encode each type (for XML, strings are easy, numbers are easy,
   commodities are a namespace/name pair, etc., while for GDA, strings are
   easy, numbers are easy, commodities are a GUID, etc.).  One problem
   with g_object_class_list_properties() is that the account has a number
   of properties (such as ending balance) which don't need to be
   persistent.  Therefore, an IGncEnginePersistenceInfo interface with a
   gnc_engine_object_get_persistence_parameters() function to return the
   same kind of info as g_object_class_list_properties() would be added
   (an alternative is to define GncObject or GncEngineObject as a subclass
   of QofObject and subclass all engine objects from it - the
   gnc_engine_object_get_persistence_parameters() could then be defined as
   a method for GncEngineObject). Actually, it would be defined for the
   engine object class objects, not the engine objects themselves.
   I think it would reduce the size of each backend.  In addition, since
   the engine object classes would supply the information about what would
   need to be saved, it would improve encapsulation and also maintenance
   in the backends as new attributes are added.  Each backend would need
   to know how to save each attribute type, and how to convert from the
   saved value if the attribute type has changed (e.g. recent sx change
   from FreqSpec to Recurrence).  The GDA backend would need to know how
   to map attribute names to column names (I don't think '-' is allowed in
   a column name, for example) and how to modify tables if the table
   column structure doesn't match the types of the attributes to be saved
   (attribute added or type changed).
   Phil

References

   1. mailto:plongstaff at rogers.com
   2. http://en.wikipedia.org/wiki/Memento_pattern


More information about the gnucash-devel mailing list