Remember that output of any action code is normally to set/alter one or more attributes. Here are a few things learned from testing complex action & export code…
Tiny steps save time in the end — especially when things are not going as they ought.
Store results in (interim attributes. You can view attribute values in many ways other than a note window's key attributes:
Indeed, as the above don't require opening a text window, the method can be more efficient
If an initial attempt at a piece of code does not work then consider:
- Starting at the smallest level - test each constituent part.
- Breaking down nested and chained expressions so that:
- Each individual expression is verified on its own. When you are sure of the individual parts can you can combine them with a greater idea of where failure may occur, incrementally adding tested code.
- Each step results in an attribute. You can then inspect interim values/data formats and check they are as expected.
- Dot-chained expressions are unchained. Break these back into individual steps as above, storing the result in a attribute: $AttrY = $AttrX.actionA().actionB() becomes $AttrZ = $AttrX.actionA(); $AttrY = $AttrZ.actionB(). Sometimes, when chaining actions, it is necessary to add parentheses to 'crystallise' the current result before the next step: e.g. $AttrX.actionA().actionB() may fail but you can try ($AttrX.actionA()).actionB().
- Don't go any further before you have tested the individual pieces - it is often a typo hidden in the middle of a long section that's obvious once each individual task is broken out.
- Using 'code' notes with built-in Code prototype. The built-in 'Code' prototype is designed for viewing code, so leverage it!
- Using a code note. The 'Code note' concept is storing action code in text of (another) note. This makes it easy to see/edit code and use intending, etc., whilst any edits still have immediate effect.
- Verify the agent query finds the right notes before adding any action code.
- If using complex code, or a code note, remember it can be useful to turn the agent off whilst editing the code.
- Using an agent to test queries intended for inline use with find(), collect() and the like. Does such an agent query return the items you expected in your action code?
- The context of action when using offset attribute reference - i.e. when addressing an attribute in another note rather than the note in context: $AnAttr("someothernote") vs. $AnAttr.
- Allowing for the possibility that some codes may not evaluate (all) inputs - i.e. they only accepts literal values. Do not assume inputs are evaluated without doing a small standalone test to prove this.
- With evaluated inputs, beware unintentional nesting of evaluations. Thus "hello" is a literal value - no evaluation needed. But, you might store that in an attribute in another note and call it by this simple evaluation: $MyString("hello note"). However, if the parameter value is something like $Name("hello note").split(").at(0), whilst still an evaluated term it consists of several nested/chained evaluations. Again, don't assume in more complex settings, test first.
- The context of execution when using agent actions - are you setting the original's attributes or just those of the alias in the agent? This matters in relation to intrinsic attributes.
- Use a new small file for your tests. Making a test rig with a smaller dataset to filter out the noise of testing on an already large/complex TBX (this also pre-empts accidental data damage from badly written user actions). Bear in mind that notes, prototypes, attributes, etc., can be drag-copied from a main to a test TBX so set-up is not as onerous as it may appear.
With regard to Export code:
- be aware of context. From which note's attributes is the code reading?
- includes cannot draw data from a note set to not export. Learn to understand the nuances of $HTMLDontExport and $HTMLExportChildren.
- links cannot be created to the content of notes exported as an inline include in another note.