第3部 コードの再構成 ~無関係な下位問題~

無関係な下位問題を見つけて抽出する

リーダブルコードに、無関係な下位問題の抽出について以下の記述がある。

1. 関数やコードブロックを見て「このコードの高レベルの目標は何か?」と自問する。
2. コードの各行に対して「高レベルの目標に直接的に効果があるのか? あるいは、無関係の下位問題を解決しているのか?」と自問する。
3. 無関係の下位問題を解決しているコードが相当量あれば、それらを抽出して別の関数にする。
引用元:Dustin Boswell, Trevor Foucher『リーダブルコード』オライリー・ジャパン出版

「何のこっちゃ?」と思っていたが、読み進めていくうちに「汎用コードを抽出する。必要に応じてメソッド化する。」と理解した。自分なりに考えた以下のコードを例にやってみよう。

//試験に合格したか判定する
function JudgePassedTest(id) {
    for (var i = 0; i < persons.length; i++) {
       if (persons[i].id == id) {
           if (persons[i].japanese.score < japanese.passing_score)
               return false;
           else if (persons[i].math.score < math.passing_score)
               return false;
           else if (persons[i].english.score < english.passing_score)
               return false;
           else if (persons[i].science.score < science.passing_score)
               return false;
           else if (persons[i].society.score < society.passing_score)
               return false;
           else
               return true;
       }
   }
   
   return false;
}

高レベルの目標は「試験合格の判定処理」なのに、無関係な下位問題「教科ごとの及第点の判定処理」がコードのほとんどを占めている。無関係な下位問題をメソッド化してみよう。

//試験に合格したか判定する
function JudgePassedTest(id) {
    for (var i = 0; i < persons.length; i++) {
       if (persons[i].id == id)
           return IsPassingScore(persons[i]);
   }
   
   return false;
}

//及第点か判定する
function IsPassingScore(person) {
    if (person.japanese.score < japanese.passing_score)
       return false;
   else if (person.math.score < math.passing_score)
       return false;
   else if (person.english.score < english.passing_score)
       return false;
   else if (person.science.score < science.passing_score)
       return false;
   else if (person.society.score < society.passing_score)
       return false;
   else
       return true;
}

「試験合格の判定処理」のコードだけになり、とても見やすくなった。さらに、メソッド化した「教科ごとの及第点の判定処理」は再利用できるようになった。

普段、コードをメソッド化することはあったが、ここまで明確な基準ではなかった。もしかすると、高レベルの目標に直接関係するコードもメソッド化してしまっていたかもしれない。。。基準を知れるのはとてもありがたいことだなぁ。

この記事が気に入ったらサポートをしてみませんか?