Заміна вкладених умовних операторів граничним оператором
Проблема
У вас є група вкладених умовних операторів, серед яких складно виділити нормальний хід виконання коду.
Рішення
Виділіть усі перевірки спеціальних або граничних випадків виконання в окремі умови і поставте їх перед основними перевірками. В ідеалі, ви повинні отримати «плаский» список умовних операторів, що йдуть один за іншим.
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 { ... } }
Розібратися в тому, що і як робить такий оператор досить складно, оскільки «нормальний» хід виконання в ньому не очевидний. Такі оператори з’являються еволюційним шляхом, коли кожна з умов додається в різні часи без думки про необхідності оптимизаціі інших умов.
Щоб спростити такий оператор, треба виділити усі особливі випадки в окремі умовні оператори, які у випадках настання граничних умов будуть відразу закінчувати виконання і повертатимуть потрібне значення. По суті, ваша мета — зробити такий оператор пласким.
Порядок рефакторингу
Намагайтеся позбутися від «побічних ефектів» в умовах операторів. Розділення запиту і модифікатора може в цьому допомогти. Таке рішення знадобиться для подальших перестановок умов.
-
Виділіть граничні умови, які призводять до виклику виключення або негайного повернення значення з методу. Перемістіть ці умови в початок методу.
-
Після того, як з перенесеннями покінчено, і усі тести стали проходити, перевірте, чи можна використати ооб’єднання умовних операторів для граничних умовних операторів, що ведуть до однакових виключень або значень, які повертаються.