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 do not 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 an 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().
- Do not go any further before you have tested the individual pieces as 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, do not 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.