Thoughts on architecture for the GDA backend

Phil Longstaff plongstaff at
Mon Dec 17 19:24:57 EST 2007

OK.  Let me try this again.  I'll send as a plain text e-mail instead of 
HTML and see if that fixes the formatting problem.

Derek Atkins wrote:
> Hi,
> Phil Longstaff <plongstaff at> 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.
>> - 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 (  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).


More information about the gnucash-devel mailing list