1
\$\begingroup\$

I have a data structure that looks like this:

interface Node {
  originalWeight: number;
  currentWeight: number;
}

where both properties are floats between 0 and 1.

To check if a node has been modified, I wrote a simple isNodeModified function:

isNodeModified(node: Node): boolean {
  return Math.abs(node.originalWeight- node.currentWeight) > this.EPSILON;
}

where EPSILON is my tolerance.

However, I also need to do a very similar comparison in a slightly different scenario, which was originally handled like this:

if (Math.abs(event.value - node.originalWeight) > this.EPSILON) {
  // do something
}

where event is another object with a value property.

To avoid duplication, I replaced both methods with something like the following:

isNodeModified(node: Node, event?: Event): boolean {
  let original = node.originalWeight;
  if (event) {
    original = event.value;
  }
  return Math.abs(original - node.currentWeight) > this.EPSILON;
}

So that I can call isNodeModified(node) or isNodeModified(node, event) depending on what I need.

Is there a better / cleaner solution to this problem?

\$\endgroup\$
  • \$\begingroup\$ Can you clarify what the purpose of event is? \$\endgroup\$ – Adam Aug 23 '18 at 13:18
  • \$\begingroup\$ @Adam it carries a value that will become the new originalWeight, but only if event.value !== currentWeight \$\endgroup\$ – bugs Aug 23 '18 at 13:28
1
\$\begingroup\$

The most concise way to write your function that's still very readable is this:

function isNodeModified(node: Node, event?: Event): boolean {
  return Math.abs((event ? event.value : node.originalWeight) - node.currentWeight) > this.EPSILON;
}

If event is passed in, the event's value is used, otherwise node's originalWeight is used.

Ternary operators are amazing for condensing simple checks/if-statements into an inline operation. I recommend using them as much as possible as long as the result is still readable and not lengthy.

\$\endgroup\$
1
\$\begingroup\$

You could create a more general function which simple compares two values. Like:

hasDifference(oldValue: number, newValue: number, offset?: number): boolean {
  const offsetToUse: number = offset === undefined ? this.EPSILON : offset;

  return Math.abs(oldValue - newValue) > offsetToUse;
}
\$\endgroup\$
  • 2
    \$\begingroup\$ offset?: number is better than offset: number | undefined as the second requires calling as hasDifference(oldV, newV, undefined) (assuming you have strict null checks on, which you should) \$\endgroup\$ – Gerrit0 Aug 23 '18 at 14:57
  • \$\begingroup\$ changed it. @Gerrit0 - would that make hasDifference(oldV, newV, null) fail the === check? \$\endgroup\$ – Nsevens Aug 27 '18 at 12:23
  • 1
    \$\begingroup\$ null !== undefined so yes. If you have strict null checks on though, Typescript will complain at compile time. \$\endgroup\$ – Gerrit0 Aug 27 '18 at 12:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.