Posts Tagged: ‘computewithform’

The Law of Unintended Consequences

1. Oktober 2014 Posted by Björn Großewinkelmann

 

Ok, so we all know that the road to becoming a Notes developer is a rocky one but there really are some things that take the cake in that regard. Today I like to talk about standard functions and that they never behave quite like you might expect them to.

Since I work primarily with LotusScript let us take a look at a very useful und often used function in the NotesDocument class, namely ComputeWithForm.

First let’s read the manual (8.5.3):


ComputeWithForm method

Validates a document by executing the default value, translation, and validation formulas, if any are defined in the document form.

Defined in

NotesDocument

Syntax

flag = notesDocument.ComputeWithForm( doDataTypes, raiseError )

Parameters

doDataTypes

Boolean. The method ignores this parameter. Specify either True or False.

raiseError

Boolean. If True, an error is raised if the validation fails. If False, no error is raised; instead, the method returns False if validation fails.

Return value

  • True indicates that there are no errors on the document.

  • False indicates that there are errors on the document.

[*snip*]



Source: http://www-01.ibm.com/support/knowledgecenter/SSVRGU_8.5.3/com.ibm.designer.domino.main.doc/H_COMPUTEWITHFORM_METHOD.html?lang=en

 

Let us just ignore interesting tidbits like “The method ignores this parameter. Specify either True or False.” and move on to the really strange stuff. So what does this method claim to do?

1) It executes validation formulas

If you work like me you will never use that feature since I always put field validations in my backend class for the following reasons:

  1. I always know where to find them, trust me that is not a small issue when it comes to complex business logic and interdependent rules.
  2. It is far easier to write such complex rules in LS than in Formula Language.
  3. You can debug LS!
  4. You can evaluate all of the rules and give the user a summary report instead of raising an error after the first evaluated rule fails to validate.

 

2) It executes Input Translation Formulas

Yep it does and you have to be aware of that. But if you use Input Translation at all you probably know what you are doing since otherwise you couldn’t.

 

3) It “executes” default values.

It does. Which is the reason why we use it so frequently so we can set all the items we need on a document that was created through backend classes or agents. One ComputeWithForm and all the default values are there. Immensely useful but Notes wouldn’t be Notes if it hadn’t some surprises in stock for us there.

 

4) It returns a Boolean to indicate whether or not the validation succeeded

Well, yes it does …kind of… maybe … if nothing else did go wrong you have no idea about….

 


based on © Andy Dean - Fotolia.com

“Default” is a just a word…

So let us unpack the more problematic und not very well documented “features” of this function and let’s start with the default values it is supposed to execute.

First if you think that “default values” refer to… well default values you are obviously new at this but don’t despair you’ll get there eventually. So no, “executing default values” does NOT ONLY mean that an item is created on the document which has the values you can specify in the “Default”-section of any of the editable fields on a given form. In fact it means a lot more than that.

ComputeWithForm also executes formulas in Computed- and ComputedWhenComposed-Fields. Which is great! But: if no “default” value is available the created item will be of type text (1280) and the value will be set to the empty string! So, arguably yes it does execute default values… if you use that term rather loosely.

… “Error” on the other hand…

If you read the description in the manual and my remarks above you might think that ComputeWithForm essentially creates all not yet existing items then executes the input translations to finalize their values before it checks those values against the validation rules. At this point the function returns either ‘true’ or ‘false’ (or raises an error if you set raiseError = ‘true’) to indicate whether or not all rules validated successfully.

But then I guess at this point you already know better than that.

Suppose you have a DBLookup in one of your computed fields and that lookup fails for whatever reason.
Right, it is an error but is it a validation error?
Even if there is no input validation specified for that field?
And what if you use [FailSilent]?
Still an error?
Surely not and that can’t possibly be treated as a validation error right!?
Well, wrong on all counts!

The type of error does not matter at all. Every single error in a formula on your document will cause ComputeWithForm to fail and to fail miserably! Because every single error, even the ones that aren’t (because of [FailSilent]), will be treated as fatal which means that ComputeWithForm will stop evaluating the document which in turn means that not all the default values will be set. One failed lookup and not another item will be evaluated!

Yes the manual states: False indicates that there are errors on the document.

But I bet you didn’t think they literally meant every possible error. And on top of that even the ones that are already handled!

Well now you know!

So if you for example use a lookup in a computed field that might fail you have to identify why that could possibly be and then check for those conditions with @If. Then ComputeWithForm will finally work as you expected it to all along...

... kind of. At least, if you know what it does and doesn't do you can work around it and might even find it useful... maybe. Of course ComputeWithForm is not the only example of ... interesting ... behavior, it is probably not even the worst one. But from what you can gather on the net a lot of people believe that it works in a lot of different ways that seem to be mutual exclusive and people are (as always) not shy about sharing incomplete information. Which, in a sense, makes this function the worst of its kind after all because people get frustrated.

But maybe I am wrong, maybe I should see stuff like this more relaxed and treat the documentation more like loose guidelines.... What do you think? And while we're at it: What do you believe to be the most atrociously under-documented or reality-bending, may-work-as-intended-on-the-fourth-Tuesday-in-February-on-a-parallel-plane-of-existence-if-it’s-not-a-leap-year-function in the Notes/Domino environment? Leave a comment and share the pain. Trust me, it's good therapy.