jeudi 21 février 2019

How to deal with nested conditional statements?

I have a series of nested conditional checks and I am trying to come up with a clean solution and avoid if{}else{} hell as much as possible. Please see the example code as a demonstration of what I am trying to achieve.

In summary, I have two objects, CACHE_FILE_AGE_LIMIT and CACHE_FILE_CURRENT_AGE and I am trying to go through a nested age check:

first check the days,
    then check hours,
       then check minutes,
           then check seconds

The idea is that, the moment we reach a greater value, for example, days are equal, then we move on hours and if we catch a greater hour value, we end the check.

Please see the example for further info.`

const CACHE_FILE_AGE_LIMIT = {
  days: 3,
  hours: 6,
  minutes: 15,
  seconds: 57
}

const CACHE_FILE_CURRENT_AGE = {
  days: 3,
  hours: 5,
  minutes: 14,
  seconds: 57
}

function timeDiff(ageObj1, ageObj2) {
  console.log('days_limit', ageObj1.days, '?', 'days_age', ageObj2.days);
  // old: days
  document.getElementById("current_days").innerHTML = ageObj2.days;
  if (ageObj1.days < ageObj2.days) {
    console.log('old (days)');
    document.getElementById("current_days").classList.add("red");
    return true;
  } else {
        // equal: days
    if (ageObj1.days == ageObj2.days) {
        document.getElementById("current_hours").innerHTML = ageObj2.hours;
      console.log('\tnext: hours');
      console.log('\thours_limit', ageObj1.hours, '?', 'hours_age', ageObj2.hours);
      if (ageObj1.hours < ageObj2.hours) {
        console.log('\told (hours)');
        document.getElementById("current_hours").classList.add("red");
        return true;
      } else {
        // equal: hours
        if (ageObj1.hours == ageObj2.hours) {
          document.getElementById("current_minutes").innerHTML = ageObj2.minutes;
          console.log('\t\tnext (minutes)');
          console.log('\t\tminutes_limit', ageObj1.minutes, '?', 'minutes_age', ageObj2.minutes);
          if (ageObj1.minutes < ageObj2.minutes) {
            // old: minutes
            console.log('\t\told (minutes)');
            document.getElementById("current_minutes").classList.add("red");
            return true;
          } else {
            // equal: minutes
            if (ageObj1.minutes == ageObj2.minutes) {
              document.getElementById("current_seconds").innerHTML = ageObj2.seconds;
              console.log('\t\t\tnext (seconds)');
              console.log('\t\t\tseconds_limit', ageObj1.seconds, '?', 'seconds_age', ageObj2.seconds);
              if (ageObj1.seconds < ageObj2.seconds) {
                console.log('\t\t\told (seconds)');
                document.getElementById("current_seconds").classList.add("red");
                return true;
              } else {
                console.log('\t\t\tNOT old (seconds)');
                document.getElementById("current_seconds").classList.add("blue");
                return false;
              }
            } else {
              console.log('\t\tNOT old (minutes)');
              return false;
            }
          }
        } else {
          console.log('\tNOT old (hours)');
          document.getElementById("current_hours").classList.add("blue");
          return false;
        }
      }
    } else {
      console.log('NOT old (days)');
      document.getElementById("current_days").classList.add("blue");
      return false;
    }
  }
}

// Populate Limits
var limit_fields = document.querySelectorAll(".limit");
for(i=0; i < limit_fields.length; i++){
                                //console.log('--->', i)
        let id = limit_fields[i].id.split("_")[1];
        let val = CACHE_FILE_AGE_LIMIT[id]
        //console.log('\tid:', id, 'val:', val);
        limit_fields[i].innerHTML = val;
    }

// Evaluate Age
document.getElementById("output").innerHTML = timeDiff(CACHE_FILE_AGE_LIMIT, CACHE_FILE_CURRENT_AGE) ? "old" : "up to date";
.tg {
  border-collapse: collapse;
  border-spacing: 0;
}

.tg td {
  font-family: Arial, sans-serif;
  font-size: 12px;
  padding: 10px 5px;
  border-style: solid;
  border-width: 1px;
  overflow: hidden;
  word-break: normal;
  border-color: black;
}

.tg th {
  font-family: Arial, sans-serif;
  font-size: 12px;
  font-weight: normal;
  padding: 10px 5px;
  border-style: solid;
  border-width: 2px;
  overflow: hidden;
  border-color: black;
}

.tg .value {
  color: blue;
  text-align: center;
  vertical-align: top;
}

.tg .current {
  color: blue;
  text-align: center;
  vertical-align: top;
}

.tg .current.red {
  color: red;
}

.tg .current.blue {
  color: blue;
}

.tg .limit {
  color: #85929E;
  text-align: center;
  vertical-align: top;
}

.tg .header {
  background-color: #ffffc7;
  text-align: center;
  vertical-align: top;
}

.tg .item {
  background-color: #ffffc7;
  font-style: italic;
  text-align: right;
  vertical-align: top;
}

.tg .empty {
  background-color: #9b9b9b;
  text-align: right;
  vertical-align: top;
}

.tg .result {
  font-weight: bold;
  font-style: italic;
  background-color: #ffce93;
  text-align: right;
  vertical-align: top;
}

.tg .output {
  background-color: #FDEBD0;
  text-align: center;
  vertical-align: top;
}
<table class="tg" style="undefined;table-layout: fixed; width: 265px">
  <colgroup>
    <col style="width: 92px">
    <col style="width: 92px">
    <col style="width: 92px">
  </colgroup>
  <tr>
    <th class="empty"></th>
    <th class="header">CURRENT</th>
    <th class="header">LIMITS</th>
  </tr>
  <tr>
    <td class="item">DAYS</td>
    <td id="current_days" class="value current">-</td>
    <td id="limit_days" class="value limit"></td>
  </tr>
  <tr>
    <td class="item">HOURS</td>
    <td id="current_hours" class="value current">-</td>
    <td id="limit_hours" class="value limit"></td>
  </tr>
  <tr>
    <td class="item">MINUTES</td>
    <td id="current_minutes" class="value current">-</td>
    <td id="limit_minutes" class="value limit"></td>
  </tr>
  <tr>
    <td class="item">SECONDS</td>
    <td id="current_seconds" class="value current">-</td>
    <td id="limit_seconds" class="value limit"></td>
  </tr>
  <tr>
    <td class="result">RESULT</td>
    <td id="output" class="output" colspan="2">up to date</td>
  </tr>
</table>

`

So as you can see, the conditional execution ends once it is clear that the hours are enough to determine the age.

Please change the values in the CACHE_FILE_CURRENT_AGE to test it.

Aucun commentaire:

Enregistrer un commentaire