Logic ideas - 5 levels.
Neil Williams
linux at codehelp.co.uk
Wed Sep 28 11:35:12 EDT 2005
On Wednesday 28 September 2005 3:06 pm, Derek Atkins wrote:
> Quoting Neil Williams <linux at codehelp.co.uk>:
> > A bit like QSF and qof_book_merge and indeed cashutil itself. To keep
> > things small and simple(r) I copy current sources into a new tree for
> > testing. It's much like creating a branch. I work with only the files I
> > need for the current critical area, making development faster.
> >
> >> I'd like
> >> to see an existing dialog of moderate complexity in terms of these
> >> rules.
> >
> > Nothing yet, I've got other things to solve first. I'll post when I've
> > got some real code.
>
> I still don't understand how this helps with User Input problem... You
> don't want to have to build a "test object" and then test it..
?? Uh?? I haven't built any code yet, I'm not into test objects at runtime,
I'm creating a separate tree to write the logic code in the first place!
No way will it "build" anything to check the logic, that's daft. I have to
build the code first though. PLEASE read the message, Derek!
I'll be building a test application that will help me develop the rules and
the code that runs the rules. It's only the rules and the logic apparatus
that gets into the main tree and that is ALL runtime stuff.
The logic layer itself is a bit of a gopher. It gets requests from user
interface inputs via the handler, it passes results back to the user
interface handler. It gets it's rules from the objects and other structs in
the layer itself (for the higher level logic) and uses those to decide on the
result. Once the dialog can enable the OK button, the data is committed to
the book upon clicking OK. In the CLI, it will work differently, that is an
incremental model where the entity is created BEFORE any parameters are
entered. The entity is then logically checked as each parameter is edited and
cashutil will free the entity if the user aborts.
That's why I don't like talking in terms of what happens with specific
widgets, the layer is widget neutral, it only cares about the logic, the data
and the objects. It's intended to fit behind the UI going to and fro to
provide answers about what to do with the user input in realtime.
The one layer will support an API that will be flexible enough to be used in a
variety of UI's. If you can provide the data, the objects and logical rules,
the logic layer will work.
If you want to create the entity first (as with the CLI), you can.
If you want to check all the data before creating the entity, you can do that
too.
Which way you do it will determine in which order the rules are called but it
won't affect the logical result because all the critical rules will still
have to be satisfied whichever way around.
> I want to
> be able to test the inputs before I translate them into an object and use
> all the object setters.
You will. That's exactly the point. But before you can do that I've got to
have a test tree that allows me to build the code. There IS no code yet.
Off the top of my head, it might go something like this:
Dialog input -> dialog_handler -> logic_layer (unchanged and untested).
logic_layer -> looks up rules for the object and parameter, does ALL the
logical checks required for that combination and sets GncLogicResult.
If == 0, calls the param->param_setfcn before returning. Only those parameters
that are suitable for a setfcn call would allow a zero result, if an object
needs >1 parameter to be logically intact, then that will be enforced. This
is the whole point, cashutil cannot know this because the logic that dictates
how parameters interrelate is hidden in the GUI. So currently, cashutil
blindly sets parameters independently of any other parameter. That's why it's
not ready for use!!!!!
Dialog receives the logic result and proceeds:
1. If 0, check if OK should be enabled by calling a summary function in the
logic layer, maybe gboolean gnc_logic_complete() or gint
gnc_logic_remaining() which returns the number of inputs that are still
required before the dialog can enable OK, again zero would mean go ahead.
2. If <>0, read the reason from the logic layer and decide how to complain
to / help the user.
The logic layer will completely replace any logic currently in the dialog that
determines if the user input is logically intact. Depending on the type of
data, this could involve one or more of the 5 logic levels - the rules being
modelled on exactly what happens now.
> It sounds like I need to modify the object, test the modification, and if
> there's a failure back out the modifications...
No. You read the input from the user, pass that back to the object with the
parameter that is meant to accept it and get back a logical result. If
successful, the data will have been committed in the same stage. If it fails,
you'll get back a reason for the refusal which you pass on to the user.
Failure just means the parameter remains unchanged and the dialog asks the
user to try again, explaining what needs to be done. Exactly as now. If the
input is OK but more inputs are required (essential fields etc.), then the
parameter can be set but the log_result is still non-zero. Again, the dialog
asks the logic layer why and passes that on to the user.
Maybe something like (off the top of my head)
GncLogicResult
gnc_logic_test(QofIdType object_type, gpointer data, QofParam param)
Whereas now in QOF you'd call qof_class_get_parameter and then
param->param_setfcn(), that would be called behind the scenes IF the rules
specify that the data can be committed.
Alternatively, other parts of the code use the objects directly with some
xaccObjectSetParam type. Instead of doing the logic in the dialog and THEN
calling the setter, you call the logic test with the UNCHECKED input data and
either report back on error or carry on to the next element. If there are no
more elements that are essential for the current object definition, the logic
layer reports that it is acceptable to commit the data and the dialog enables
the OK / the CLI exits the edit sub-shell.
Dialogs that use >1 object will be able to test one against another because of
the higher level rules - 4 and 5. The dialog won't have to do any of that
itself. The objects declare their rules at registration and higher rules are
added at application startup.
I'm taking the logic out of the dialog - the dialog reads the input data in
realtime, it delegates the job of checking it logically to the logic layer
and doesn't have to bother setting the data itself.
The current step(s) in the dialog handler that actually check the incoming
data would be moved into the logic test so that the CLI could use the same
rules.
You get a result immediately that you read the data from the dialog input, the
whole point is that the dialog doesn't wait until OK is clicked, it checks
everything as it comes in, by passing the incoming data to the logic layer.
The rules specify which of the 5 levels get checked for which parameters and
which objects.
> It also means I can't do
> real-time testing (e.g. enable the OK button) on user inputs because I'm
> contantly having to create test objects...
Uh??? There are NO TEST OBJECTS! There will be a test tree for me to develop
the code but you'll never see any of that, let alone use it to create
anything.
In fact, the dialog may not actually be creating anything itself, the dialog
just passes the data to the logic layer and if all the correct data is
available for a new entity, it would be created and populated.
New Account could simply check each input against the logic layer and then
leave the logic to create the actual account - but only when the logic layer
is satisfied that the rules have been met.
> Short of creating a UI-Widget-Independent input layer, which is...
> painful.. I
> just don't see how to solve this problem in a UI-independent way, and
> your five
> levels still don't help with this problem.
Might that be because you're still reading them as file level tests?
This is a layer, it's a runtime layer, it involves no test objects or building
anything at runtime. It simply moves the logic from the dialog to the logic
layer so that the same logic can be used by a non-GUI, specifically,
cashutil.
It simply replaces the logic in the dialog with a single call to the logic
layer for each data input that both checks the data AND actions the changes
IF the logic is good.
The logic is a mix of QofObject and QofClass rules. i.e. some rules operate
solely on the object definition (static data) and don't need a real entity.
Others would create the entity if lower logic levels are OK and use that to
check against other entities. The entity would remain unless the user cancels
the entire dialog. So where the current GUI creates one entity, the GUI will
delegate that role to the logic layer which will create just the one entity.
No spurious entities, subject to undo and user cancel.
--
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/20050928/2042cf51/attachment.bin
More information about the gnucash-devel
mailing list