リファクタリングの実例1:第1回Advertisement元となるソースコード
※ここで登場するコードは某所で実際に稼動しているコードをアレンジして(雰囲気的には、ほとんどそのまま)乗せています。このシステムは短いスパンでの修正・リリースという形式で開発を行っているプロジェクトで作成され、今後も多くの変更が加えられると予想されるため、変更に強いコードでなければなりません。
Product クラス
public class Product{
public Product(String name, String teika){
this.name = name;
this.teika = teika;
}
/** 製品名 */
public String name;
/** 製品の定価 */
public String teika;
/** 製品自体にエラーが存在するか */
public boolean error;
}
Main クラス(クライアント) import java.util.regex.Matcher; import java.util.regex.Pattern; /** * 製品を利用するクラス */ public class Main{ public static void main(String[] args){ // 製品の作成 Product product = new Product("name", "1000"); // エラー設定 Pattern pattern = Pattern.compile("[A-Za-z0-9]+"); Matcher matcher = pattern.matcher(product.name); product.error = !matcher.matches(); pattern = Pattern.compile("[0-9]+"); matcher = pattern.matcher(product.teika); product.error = product.error | !matcher.matches(); // エラー判定 if(product.error){ System.out.println("この製品は内部にエラーを含んでいます。"); }else{ System.out.println("この製品にエラーはありません。"); } } }このプログラムでは Product クラスは製品を表し、内部に名前と価格を保持している。クライアントは製品を作成し、エラーが含まれていないかチェックを行った後、製品を利用する。 問題点を考えるAdvertisement |
ショートカット・634・634ブログ ・このカテゴリのトップページに戻る ・Incubator(Pukiwiki) ・634ラボ UIコレクションギャラリー ZO-3ジェネレーター サイト検索Y!ログール |
まず、Product クラスのメンバ変数(name, teika)が public となっているため、クライアント側で Product の内部構造に依存するコードが書かれている。詳しい話はカプセル化を参照。
よって、次の問題が見つかる。
- Productクラスの変数の型を変更した場合、Product・クライアント両方のコードを修正しなければならない。
次にエラーチェックに注目してみるProduct クラスは複数のクライアントから利用されることが考えられる。この場合、次の問題点が考えられる。
さらに次の要求を、常に満たしていなければならない。
- プログラムの振る舞いを変更してはいけない。
- エラーチェック処理のロジックは複数パターンあり、クライアントによって異なる。
以上の問題を踏まえ、リファクタリングを行うことにする。