WeSearch

Five Evaluators, One Pattern: Scaling Conditional Logic Across a Form

·21 min read · 0 reactions · 0 comments · 1 view
Five Evaluators, One Pattern: Scaling Conditional Logic Across a Form

Part 8 of the series: "Extending bpmn-io Form-JS Beyond Its Limits" By the time I had built the...

Original article
DEV Community
Read full at DEV Community →
Full article excerpt tap to expand

try { if(localStorage) { let currentUser = localStorage.getItem('current_user'); if (currentUser) { currentUser = JSON.parse(currentUser); if (currentUser.id === 754819) { document.getElementById('article-show-container').classList.add('current-user-is-article-author'); } } } } catch (e) { console.error(e); } Sam Abaasi Posted on Apr 28 Five Evaluators, One Pattern: Scaling Conditional Logic Across a Form #camunda #bpmn #bpmnio #javascript Part 8 of the series: "Extending bpmn-io Form-JS Beyond Its Limits" By the time I had built the third evaluator, I noticed something. The code looked almost identical to the first two. The same constructor structure. The same event subscriptions. The same state Map. The same change detection. The same _evaluating flag. Only the specific thing each evaluator did with its results was different. I had accidentally designed a pattern without realizing it. The fourth and fifth evaluators were written by copying the third, changing the class name, and swapping out the specific evaluation and application logic. Each took about 30 minutes instead of the days the first one took. This article documents that pattern — the six responsibilities every evaluator shares, what's unique in each of the five I built, and the template you can use to build your own. The Problem Form-JS supports static properties: a field is disabled or it isn't, required or it isn't, hidden or it isn't. These are set in the schema at design time and don't change at runtime. What Form-JS doesn't support out of the box is dynamic properties: a field that becomes disabled when status = "closed", required when category = "other", hidden when role != "admin". For these you need runtime evaluators — classes that watch the form data for changes and update field states accordingly. The challenge is building evaluators that: Don't evaluate unnecessarily (every changed event on a 50-field form would be 50 evaluations per keystroke without guards) Don't cause infinite loops (evaluation → _setState → changed event → evaluation → ...) Apply results correctly (different properties apply differently — display: none for hidden, disabled attribute for disabled, schema mutation for required) Stay in sync with the schema (when the form designer changes a FEEL expression in the editor, the runtime should update immediately) Building this correctly for one property is work. Building it for five without a shared pattern is maintenance debt. What I Tried First My first evaluator — BindingEvaluator, for computing derived field values — worked. Then I built HideEvaluator. I copied large sections from BindingEvaluator, changed some variable names, and added the hide-specific DOM logic. Then I needed to fix a debounce timing issue in BindingEvaluator. I fixed it there. I forgot to fix it in HideEvaluator. Two weeks later a bug report came in about hide logic not updating reliably. The problem was obvious in retrospect: I had copied code instead of extracting the pattern. Every fix needed to be applied to five files. Every improvement needed to be replicated five times. The right approach — which I arrived at after building all five — is to understand the six shared responsibilities first, extract those into a shared base, and let each evaluator implement only what's unique. I'm presenting the pattern here before the implementations so you don't make the same mistake I did. The Six Shared Responsibilities Every evaluator in my system does exactly these six things,…

This excerpt is published under fair use for community discussion. Read the full article at DEV Community.

Anonymous · no account needed
Share 𝕏 Facebook Reddit LinkedIn Email

Discussion

0 comments

More from DEV Community