4

For example, suppose my input data and UI is not in 1 to 1 relationship: enter image description here

html:

<script>
aChanged=function(){
};

bChanged=function(){
};

cChanged=function(){
};
</script>
a:<input id="a" onchange="aChanged()"/>,b:<input id="b" onchange="bChanged()"/>,c:<input id="c" onchange="cChanged()"/><br/>
a+b=<span id="a+b"></span><br/>b+c=<span id="b+c"></span><br/>a+c=<span id="a+c"></span>

which change "a" needs to refresh "a+b" and "a+c". My question is, how should I write the update UI functions?

Style 1 : define more methods but updates requires UI only:

aChanged=function(){
  updateAB();
  updateAC();
};

bChanged=function(){
  updateAB();
  updateBC();
};

cChanged=function(){
  updateBC();
  updateAC();
};

updateAB=function(){
  document.getElementById("a+b").innerHTML=Number(document.getElementById("a").value)+Number(document.getElementById("b").value);
};

updateBC=function(){
  document.getElementById("b+c").innerHTML=Number(document.getElementById("b").value)+Number(document.getElementById("c").value);
};

updateAC=function(){
  document.getElementById("a+c").innerHTML=Number(document.getElementById("a").value)+Number(document.getElementById("c").value);
};

Style 2 : define less methods but it may update some UI unnecessarily (eg:change a may also refresh b+c):

aChanged=function(){
  updateABC();
};

bChanged=function(){
  updateABC();
};

cChanged=function(){
  updateABC();
};

updateABC=function(){
  document.getElementById("a+b").innerHTML=Number(document.getElementById("a").value)+Number(document.getElementById("b").value);
  document.getElementById("b+c").innerHTML=Number(document.getElementById("b").value)+Number(document.getElementById("c").value);
  document.getElementById("a+c").innerHTML=Number(document.getElementById("a").value)+Number(document.getElementById("c").value);
};

Which style should I use?

2

There isn't a clear answer to this, as the benefits and drawbacks are situational. I'll list a few of the factors that come to mind.

To summarize the below finding: style 2 is vastly superior because it requires less effort and will generally lead to less bugs. However, style 1 is superior if you value runtime performance more than development effort (and there is a meaningful performance difference between the two).


Sheer effort

Suppose you have 5 values, and you calculate 32 distinct sums (back of the napkin, that is how many distinct additions you can do with 5 values). Each of the 5 values will be used in 16 of the sums, and will be ignored by the other 16 of the sums.

  • Using style 1, you will have to write 16 UpdateThisParticularSum() calls for each of the textbox change events, which is 80 checks in total. You will have 32 distinct UpdateThisDistinctSum() methods but you will have to call them 80 times in total.
  • Using style 2, your UpdateEverythingAtOnce() method is going to have to recalculate the 32 values.

Because the amount of relations between the values (how they can be added or not added together) is maximized in this example, it becomes cumbersome to have to manually deal with it all.

Suppose you have 32 values, and you calculate 4 distinct sums (= you minimize the amount of relations between the values). It's unclear how often each value is used in the sums, but let's assume an equal distribution and thus each value is used twice in total, so that is 64 used values in total for all sums.

  • Using style 1, you will have to write 4 UpdateThisParticularSum() calls for each of the textbox change events, which is 64 checks in total. You will have 4 distinct UpdateThisDistinctSum() methods but you will have to call them 64 times in total.
  • Using style 2, your UpdateEverythingAtOnce() method is going to have to recalculate the 4 values.

In either case, style 1 is always going to end up with a higher linecount. The more sums you calculate from a given amount of values, the more excessive the increase in line count becomes.

Winner: Style 2.


Performance

Addition is a simple calculation that has a negligible performance cost. Let's say we're calculating something massively more complex that takes 10 seconds. I'll still refer to them as "sums" to remain consistent with my answer, but you can assume that they are some abitrary complex mathematical task.

3 values and 3 sums (your example)

  • With style 1, each input only affects 2 sums. This results in a 20 sec recalculation time.
  • With style 2, each input recalculates all 3 sums. This results in a 30 sec recalculation time.

32 values and 4 sums (my example 2)

  • With style 1, each input only affects 2 sums. This results in a 20 sec recalculation time.
  • With style 2, each input recalculates all 4 sums. This results in a 40 sec recalculation time.

5 values and 32 sums (my example 1)

  • With style 1, each input only affects 16 sums. This results in a 160 sec recalculation time.
  • With style 2, each input recalculates all 32 sums. This results in a 320 sec recalculation time.

A particular input which only affects 2 out of 20 sums

  • With style 1, this results in a 20 sec recalculation time.
  • With style 2, this results in a 200 sec recalculation time.

Style 1 will always be faster here. At the very worst, if an input happens to be used in all sums, it will have equivalent performance (because then it does recalculate all sums)

The more sums there are, and the more sums that are not affected by a particular input and thus don't need recalculation; the bigger your performance gains will be.

Winner: Style 1.


Bugs

Style 1 requires you to link every sum to its input values. You're using 3 values and 3 sums. Think about what it would take to do this for 10 values and 10 sums. The problem quickly escalates to unmanageable proportions.
The more work you have to do, the bigger the chance of making a mistake somewhere. Especially with repetitive-but-always-slightly-different code, you're liable to make a copy/paste error somewhere or write the wrong thing at the wrong time.

Style 2, however, does not require any link between a sum and its input values. You omit the link and instead take a "recalculate it all" approach. The good thing about this is that bug will becomes much easier to spot. Either all recalculations work, or none of them do.

Winner: Style 2.

0

You could always take a third option and implement an Observer pattern. Just like @Flater noted, this will have pros and cons that you will need to consider when making your choice.

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.