Hi all,

it seems to me that '+Need' causes expectations it cannot fulfill. I can
sometimes see E/R models with '+Need' in almost each relation, but in
reality it is not as useful as it might appear. Let me try to explain
the rationale behind it.

The philosophy of PicoLisp is to give a maximum of control and
flexibility to the programmer. The entity/relation framework in
"lib/db.l" is rather low-level: It automatically maintains all necessary
data structures, but it does not stop the programmer from doing
something "illegal". He can directly manipulate all those structures
with list- and symbol-functions, at any time.

So what is a '+Need' class supposed to do? It should enforce the
presence of certain properties in a database symbol.

But *when* should it do that? When a new symbol is created? This is not
possible, because a new symbol does not have any properties at all. The
properties might be 'put' one after another, so there is never the right

And *how* should it do that? Issue a hard error (e.g. with 'quit' or
'throw')? This would not be wise, because it does not allow the graceful
handling of such situations in higher layers.

Therefore, the '+Need' class is strictly "cooperative". It supplies the
'mis>' method, which can be called from higher layers as needed.
Currently, this is from the 'chk>' method of fields in "lib/form.l", and
also from the interactive 'update' function in "lib/sq.l". In a similar
way, it could be called by other custom database functions.

The 'chk>' message is sent to each field in a form whenever a button is
pressed. When any such method invocation returns non-NIL (i.e. an error
string), processing of that button press is aborted, and the error
message is displayed to the user. The result is that the user cannot
input a value into a field for which the field's 'chk>' method signals
an error, because the only way to get values from the GUI into the
database is via button presses.

But even so, this is still too "hard" in certain cases. Imagine an
entity class which has '+Need' for several relations. When an empty form
for such an object is presented to the user, he will not be able to
press any buttons without an error before he has filled in all required
fields. This might sound ok at the first sight, but can be an annoyance
in practical use. For a typical application, for the very act of filling
those fields, a button press is often necessary to present a search
dialog or a choice list to the user, making it virtually impossible to
fill in the form. In addition, why should we not allow the user to fill
only part of the form, save it, continue with some other work and resume

In essence, my rule for '+Need' is: Use it only for such relations where
the *program* guarantees that a value is initialized before that object
is presented to the user.

Look, for example, at the order class in "app/er.l":

   (class +Ord +Entity)
   (rel nr  (+Need +Key +Number))                  # Order Number
   (rel dat (+Need +Ref +Date))                    # Order date

There are two '+Need' relations. A new order is always created with both
values: The "New" button in the 'choOrd' function calls (see
"app/gui.l", line 234):

   '(newUrl '(+Ord) '(nr genKey 'nr '+Ord) 'dat (date))

That is, the new order is always initialized with a newly generated,
unique order order number 'nr', and the order date 'dat' set to "today".

When the user later edits such an order, it is not possible for him to
delete the date (though he might change it) because the 'mis>' method of
'+Need' will complain.

Other cases of 'mis>' are much more useful, like in the '+Key' class,
disallowing a user to input a conflicting value into an attribute with a
unique key. Or other 'chk>' methods, like in '+DateField', which
guarantees only legal date formats.

The best, most flexible, and most user-friendly way to implement runtime
checks is IMHO a dedicated 'check>' method. There is an example for it
also in "app/er.l" and "app/ord.l".

The 'check>' message is always sent to an object when something has to
be done with that object, not while it is being edited. In the "app/"
example it is only for printing, but in a real application it will be
used also when an order is booked, or otherwise calculated with or
operated on. This is the moment when all data *must* be present, and
this is also the only moment where circular constraints can be checked.

The above explanations refer the the 'form' GUI, but they are valid for
any interactive framework.

My recommendation is to use '+Need' with great care, or perhaps not
at all, and put constraints resulting from the application logic
into arbitrarily sophisticated 'check>' methods.

- Alex

Reply via email to