Заміна вкладених умовних операторів граничним оператором
Проблема
У вас є група вкладених умовних операторів, серед яких складно виділити нормальний хід виконання коду.
Рішення
Виділіть усі перевірки спеціальних або граничних випадків виконання в окремі умови і поставте їх перед основними перевірками. В ідеалі, ви повинні отримати «плаский» список умовних операторів, що йдуть один за іншим.
public double getPayAmount() { double result; if (isDead){ result = deadAmount(); } else { if (isSeparated){ result = separatedAmount(); } else { if (isRetired){ result = retiredAmount(); } else{ result = normalPayAmount(); } } } return result; }
public double getPayAmount() { if (isDead){ return deadAmount(); } if (isSeparated){ return separatedAmount(); } if (isRetired){ return retiredAmount(); } return normalPayAmount(); }
public double GetPayAmount() { double result; if (isDead) { result = DeadAmount(); } else { if (isSeparated) { result = SeparatedAmount(); } else { if (isRetired) { result = RetiredAmount(); } else { result = NormalPayAmount(); } } } return result; }
public double GetPayAmount() { if (isDead) { return DeadAmount(); } if (isSeparated) { return SeparatedAmount(); } if (isRetired) { return RetiredAmount(); } return NormalPayAmount(); }
function getPayAmount() { if ($this->isDead) { $result = $this->deadAmount(); } else { if ($this->isSeparated) { $result = $this->separatedAmount(); } else { if ($this->isRetired) { $result = $this->retiredAmount(); } else { $result = $this->normalPayAmount(); } } } return $result; }
function getPayAmount() { if ($this->isDead) { return $this->deadAmount(); } if ($this->isSeparated) { return $this->separatedAmount(); } if ($this->isRetired) { return $this->retiredAmount(); } return $this->normalPayAmount(); }
def getPayAmount(self): if self.isDead: result = deadAmount() else: if self.isSeparated: result = separatedAmount() else: if self.isRetired: result = retiredAmount() else: result = normalPayAmount() return result
def getPayAmount(self): if self.isDead: return deadAmount() if self.isSeparated: return separatedAmount() if self.isRetired: return retiredAmount() return normalPayAmount()
getPayAmount(): number { let result: number; if (isDead){ result = deadAmount(); } else { if (isSeparated){ result = separatedAmount(); } else { if (isRetired){ result = retiredAmount(); } else{ result = normalPayAmount(); } } } return result; }
getPayAmount(): number { if (isDead){ return deadAmount(); } if (isSeparated){ return separatedAmount(); } if (isRetired){ return retiredAmount(); } return normalPayAmount(); }
Причини рефакторингу
«Умовний оператор з пекла» досить просто відрізнити. Відступи кожного з рівнів вкладеності формують в нім виразну стрілку, що вказує направо:
if () { if () { do { if () { if () { if () { ... } } ... } ... } while (); ... } else { ... } }
Розібратися в тому, що і як робить такий оператор досить складно, оскільки «нормальний» хід виконання в ньому не очевидний. Такі оператори з’являються еволюційним шляхом, коли кожна з умов додається в різні часи без думки про необхідності оптимизаціі інших умов.
Щоб спростити такий оператор, треба виділити усі особливі випадки в окремі умовні оператори, які у випадках настання граничних умов будуть відразу закінчувати виконання і повертатимуть потрібне значення. По суті, ваша мета — зробити такий оператор пласким.
Порядок рефакторингу
Намагайтеся позбутися від «побічних ефектів» в умовах операторів. Розділення запиту і модифікатора може в цьому допомогти. Таке рішення знадобиться для подальших перестановок умов.
-
Виділіть граничні умови, які призводять до виклику виключення або негайного повернення значення з методу. Перемістіть ці умови в початок методу.
-
Після того, як з перенесеннями покінчено, і усі тести стали проходити, перевірте, чи можна використати ооб’єднання умовних операторів для граничних умовних операторів, що ведуть до однакових виключень або значень, які повертаються.