Ancillary logic ideas

Neil Williams linux at codehelp.co.uk
Fri Sep 9 17:11:32 EDT 2005


On Friday 09 September 2005 2:19 am, David Hampton wrote:
> At the moment I know of no logic in the GUI that is not also enforced in
> the engine.

It is only enforced by custom, not by code. e.g. It is perfectly possible to 
create an entity that has incomplete data and it is also perfectly acceptable 
to do so in certain situations. It is because each parameter of an instance 
can be set individually. The current GUI uses in-situ rules to validate the 
input - I'm looking at ideas on how this can be shared with the CLI, if only 
to prevent duplication.

> These reason that these checks have been embedded in the 
> GUI code to enhance the user experience by providing immediate feedback.

True - and I need the same in the CLI, not only to provide a familiar user 
experience but primarily to provide data integrity assurance. (Something that 
is clearly lacking in the current CashUtil.)

> For example, a "bank" account must have a name and be denominated in a
> currency not a stock.

This is not coded in any part of the current Account object, it is coded in 
some internal functions but generally raises an assertion failure rather than 
a user error.

> The account creation code in the engine should 
> enforce this (I have no idea if it does),

It never has. It's back again to QOF not knowing the difference between 
accounts and watermelons. Only the object knows what an Account should 
contain and this is currently not tested by the engine.

As CashUtil only *has* the engine and the objects, some of the logic in the 
current dialogs should be available in the object. Other rules may require 
different solutions.

> but there's absolutely no 
> reason to wait until the user has filled out the entire dialog and
> clicked the OK button before informing them about these restrictions.
> It should be integrated into the dialog the user is filling out.  For
> example, the OK button on the dialog should not be enabled until after
> the user has entered an account name.  As far as I'm concerned, Gnucash
> needs to do more of this, not less.

OK - the same logic handler could be used for this validation. In the GUI it 
wouldn't have to wait for OK, it could -as now - be used to *enable* the 
button. That would provide a simple interface to maybe add the same principle 
to other dialogs.

> > This is the extra layer that was discussed here some time ago
>
> Got a pointer?
https://lists.gnucash.org/pipermail/gnucash-devel/2005-July/013379.html
https://lists.gnucash.org/pipermail/gnucash-devel/2005-July/013397.html
https://lists.gnucash.org/pipermail/gnucash-devel/2005-July/013378.html

In time, I'll put some form of flow or control diagram together that we can 
pass round and improve. 

> Why would you want to allow incomplete objects to exist in the first
> place?

Data mining. This is implicit in the idea of partial books - a book that 
contains insufficient data for GnuCash to render as an account tree. This 
*could* just mean that it contains no AccountGroup objects. At the other 
extreme it could mean a book containing all transactions that match a SQL 
query and no accounts, groups or anything else.

Merging this data back into GnuCash requires some form of data validation at 
the very least.

I first came across this problem with qof_book_merge and it isn't fully 
solved. I had to implement two specific functions to iterate over the book 
after the merge and try to sort out the AccountGroup references.

> All the required parameters for an object should be supplied 
> with the object is first created.

In the GUI they are and always have been. However, this kind of validation 
could also be useful with other import mechanisms like QIF and OFX.

> Cashutil doesn't accept multiple parameters at the same time?

Not yet. It could accept a couple but it's still early days and the interface 
is not sufficiently complex yet. I'm trying to keep the underpinning shell 
generic (so that other QOF programs can use it) and CashUtil will then add 
specialised functions that support this kind of data entry:

> E.G. 
> "create account type bank currency GBP parent xyz"?

There is an implicit assumption in that line: You know that both currency and 
parent are considered "required".

If you break that command down, it is:
<command> <object> <parameter> data <parameter> data <parameter> data.

What is missing is WHICH parameters are important:

add account desc "test account" notes "dummy" code "why not?"

Doesn't do the same job but - to the command parser - looks just the same.

I want to add that functionality to CashUtil and it is exactly these 
assumptions and implicit "required" fields that need to be identifiable. I 
feel it best that the objects define such things themselves.

The "required fields" for any object are completely object-specific and I'd 
like some generic way of defining such rules. It's not necessarily difficult 
- but it does require that all these rules are identified clearly.

In order to make a sensible mechanism for such declarations, I need clear 
examples of this kind of rule - the more the merrier. I can do so much from 
direct observation of the current GUI but I'd like to provide some method of 
categorising and organising each one - if only to help express rules in other 
objects.

> That command should 
> give you an object that passes the integrity checks for an account.  All
> other account fields are optional and can be checked when they are
> added.

Agreed. At present, none of this is known to QOF. Any parameter of any object 
is equally valid as any other, whether it contains a NULL or not. I'm seeking 
to be clear on what does and does not constitute a "required" parameter for 
each object.

> I have no problem if you want to add validation functions for objects,
> but I will object to any changes that make the GUI less responsive to
> users.

I'm seeking to help you make it MORE responsive, use validation more 
frequently in a standard and common manner so that you have a single function 
to call for each instance you want to verify - no matter what *type*.

The UI developer should never have to worry whether their data integrity check 
has missed some inherent component of the object. Equally, these tests should 
NOT be re-implemented in multiple places - if the object is updated, it would 
be best to have the tests in one place. Also, the object is uniquely placed 
to do the tests themselves as many would involve access to private object 
variables.

> If the handler is capable of eliciting more data from the user, then you
> need two handlers.  One for Gnucash and another for Cashutil.

Each application uses their own.

> How is 
> this any different that having the logic in the GUI and also in the
> cashutil cli?

The differences are:

1. The validation is always performed over the same parameters in all 
applications using the object.

2. The validation is performed in the same manner, using the same tests (as 
the tests live in the objects in this case)

3. It is the user feedback that is implemented differently in each case. The 
validation would return some kind of data struct that tells the UI what is 
wrong, if anything, and some information on what can be done to fix it.

The application takes the data - from the object definition - and uses it to 
communicate with the user. In the case of the GUI by e.g. enabling a disabled 
OK button if successful etc.

The logic itself - in the example of the account above - is specific to the 
Account object and can be handled in the object. It is not currently.

> If you want consistency the handler should only validate 
> the object, not validate it and try to elicit missing information.

Did I say that? I didn't mean that. The handler is in the application and it 
calls the object (with the instance) and asks if this constitutes a valid 
object - according to the logic inherent within the object. What I would like 
is that this is more than a simple gboolean - the object test routine should 
list the parameters or tests that failed and thereby provide some useful 
context for the handler (in the application) to use.

UI -> data input
Handler -> this is an instance of X object, call the logic test routine for X.
Object -> receive the entity as is and run internal tests on validity.
Object -> return success or data on reasons for failure
Handler -> communicate any reasons for failure to the user or allow user to 
proceed.
UI -> wait for next input.

No matter where the data is entered, it should be easy to use exactly the same 
tests.

> If 
> the object isn't valid the handler should return an error code to
> indicate failure (or an bitmask to indicate what failed).  Leave the
> eliciting of data to the appropriate UI code.

I was thinking of a little more data than just a bitmask - this could be 
enough when the application understands the object natively (i.e. the 
application developers understand the object) but I'd like to make it so that 
the same validation could be performed on a generic object. Let the object 
developer define the test routines and use those.

It's much like the current test routines that are part of the build itself - 
whereas currently we have to think how to test each operation/object 
individually, these tests could be re-implemented and used within the program 
itself.

-- 

Neil Williams
=============
http://www.data-freedom.org/
http://www.nosoftwarepatents.com/
http://www.linux.codehelp.co.uk/

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
Url : http://lists.gnucash.org/pipermail/gnucash-devel/attachments/20050909/17ffd84d/attachment.bin


More information about the gnucash-devel mailing list