Index: [Article Count Order] [Thread]

Date:  Wed, 14 Jan 2004 13:24:45 +0900
Subject:  【オブジェクト倶楽部: 2004-02 号】

       ┏━━━━━━━━━━━━━━━━━━━━━━━━━━■
       ┃                         ■┃
      ●┃● ● オ ブ ジ ェ ク ト 倶 楽 部   ■ ┃
       ┃                       ■  ┃
       ┗━━━━━━━━━━━━━━━━━━━━━━■━━━┛
                          No.30 2004/01/14

■ I N D E X
┃
┣【新年ご挨拶-その2】
┗【プログラミング】リファクタリング−プログラミングの体質改善 [3]

〇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  〇  新年ご挨拶−あけましておめでとうございます-その2
   〇 〇━━━━━━━━━━━━━ ━━・ 
遅くなりましたが、あけましておめでとうございます。
平素は、オブジェクト倶楽部の活動にご参加頂きありがとうございます。

事務局を担当させて頂いております加藤です。前回の平鍋さんのご挨拶に引き
続き、少々時間を頂いてお礼と本年のオブジェクト倶楽部の活動に関してお話
させていただければと思います。

お蔭様で、オブジェクト倶楽部は、このメルマガを始め、イベントや勉強会な
どを通じて、ソフトウェア技術者の交流の場として活動してまいりました。こ
れもみなさまのご理解とご協力があってのことと感謝すると同時にお礼を申し
上げます。

本年度は、Webサイトのリニューアルを今春をめどに計画しております。単なる
情報発信に止まらず、平鍋さんのご挨拶にあった「双方向」のコミュニケーショ
ンが取れるように遊び心を入れたサイトを企画しております。
また、昨年のクリスマスイベントに引き続き、第2回を予定しております。日
時などの詳細は後日お知らせいたします。前回のイベントで頂いたご要望を取
り入れオブジェクト倶楽部らしいイベントにしたと思っております。
新たな企画として、今年から勉強会を開催したいと思います。月に1回程度ご
賛同いただける方に集まり頂き、決めたテーマについて勉強をしていければと
思っています。当初は、永和コンサルティンググループの天野さん、懸田さん、
北野さん、山田さんを中心にそれぞれの専門のテーマに関して勉強会を開催し
ていく予定です。これについても、後日、詳細をお知らせいたします。
なお、イベントや勉強会についてご要望等がありましたら、事務局までご連絡
ください。お待ちしております。

最後になりましたが、本年も昨年に引き続き、オブジェクト倶楽部をよろしく
お願い致します。(事務局長) 

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━1 s t ■━
■
┗【プログラミング】リファクタリング−プログラミングの体質改善 [3]

梅田です。あけましておめでとうございます。今年もよろしくお願いします。
さて、前回は不吉な匂いから『重複したコード』を紹介しました。今回は予定
通り『スイッチ文』を紹介します。スイッチ文の問題は、同じ分岐が複数存在
すると、タイプが増えたときに全ての分岐に手を入れる可能性が生じることで
す。1つのクラス内で複数存在する分にはそれほど不便に感じませんが、膨大
なクラス群のどこに同じ分岐が存在しているか分からないときなどは、修正漏
れがないことを、神様に祈ってしまうことでしょう。現在では、Eclipseなど
の便利なツールによって、全ての箇所を簡単に検索できますが、それでもうん
ざりしちゃいますよね。

というわけで、スイッチ文は同じ分岐が複数存在するときに、メンテが大変に
なるという問題を抱えています。もちろん、わずかな箇所でしか分岐がなく、
今後もタイプが増えないようなケースでは、無理にリファクタリングする必要
もないでしょう。

レンタルビデオを表現した次のようなコードはどうでしょう? タイプコード
を定義し、色々な処理でタイプにより動作を切り分けています。
-----------------------------------------------------------
public class RentalVideo {
  public static final int REGULAR = 0;
  public static final int NEW     = 1;

  private int type;
  private String title;  // setter,getterは省略
  .....
  public int getBasePrice() {  // 基本料金
    switch (type) {
      case REGULAR: return 300;
      case NEW    : return 400;
    }
  }

  public int getDeferredPrice(int deferredDays) {  // 延滞料金
    switch (type) {
      case REGULAR: return 100 * deferredDays;
      case NEW    : return 200 * deferredDays;
    }
  }
}
-----------------------------------------------------------
同じ分岐がここ以外にもたくさん出てきそうな雰囲気ですよね。そういえば、
昔Cプログラミングで、こんなのたくさん書いたなぁ....(Javaになってから
は内緒)。このクラスをオブジェクト指向らしいコードにリファクタリングし
てみましょう。

『継承による解決』
オブジェクト指向といえば、継承によるポリモフィックな動作でしょう!
というわけで、次のようなコードにリファクタリングしました。タイプコード
は無くなりましたし、すっきりしましたね。
-----------------------------------------------------------
public abstract class RentalVideo {
  private String title;  // setter,getterは省略
  public abstract int getBasePrice();      // 基本料金
  public abstract int getDeferredPrice();  // 延滞料金
}

public class RegularVideo extends RentalVideo {
  public int getBasePrice() {
    return 300;
  }
  public int getDeferredPrice(int deferredDays) {
    return 100 * deferredDays;
  }
}

public class NewVideo extends RentalVideo {
  public int getBasePrice() {
    return 400;
  }
  public int getDeferredPrice(int deferredDays) {
    return 200 * deferredDays;
  }
}
-----------------------------------------------------------
でもよーく考えてください。新しいビデオはいつになったら安くなるのでしょ
う。いつまで経ってもレンタル料が高いままだったら大変ですよね。また、あ
るタイミングでNewVideoオブジェクトをRegularVideoオブジェクトとして作り
直すのも嫌な感じです。
今回の題材にはそれほどマッチしませんでしたが、「犬」「猫」のようにタイ
プが動的に変化しないものに対しては、適切な解決法だといえるでしょう。そ
れでは別な作戦を考えてみることにします。

『State/Strategyパターンによる解決』
別な作戦ということで、文字通りStrategyです。今回の題材ではStateと言っ
たほうが適切ですかね。
こちらもポリモフィズムを利用することで、次のようなコードに変更されます。
オブジェクトにタイプがあるのではなく、タイプに見合った算出方法を保持す
る解決法です。
-----------------------------------------------------------
public class RentalVideo {
  private String title;  // setter,getterは省略
  private Price price;   // 料金算出を司る
  .....
  public int getBasePrice() { return price.getBasePrice(); }
  public int getDeferredPrice() { return price.getDeferredPrice(); }
}

public interface Price {
  public int getBasePrice();      // 基本料金
  public int getDeferredPrice();  // 延滞料金
}

public class RegularPrice implements Price {
  public int getBasePrice() {
    return 300;
  }
  public int getDeferredPrice(int deferredDays) {
    return 100 * deferredDays;
  }
}

public class NewPrice implements Price {
  public int getBasePrice() {
    return 400;
  }
  public int getDeferredPrice(int deferredDays) {
    return 200 * deferredDays;
  }
}
-----------------------------------------------------------
時が経ちビデオが古くなってもビデオオブジェクトが変化するわけではなく、
料金の算出法が変化します。まさに今回の題材にぴったりな解決法ですね。

今回は、不吉な匂いから『スイッチ文』を紹介し、解決法としては『継承によ
る解決』と『State/Strategyパターンによる解決』の2つを取り上げました。
表現したいもののタイプが動的に変化するかどうかを判断することが、解決法
選択の鍵になるでしょう。
次回は、不吉な匂いから『長すぎるメソッド』を紹介する予定です。わかりに
くい点や質問などは随時とりあげていきたいと思いますので、気軽にご意見を
お寄せください。お待ちしております。(梅田)
_______________________________________________________________________
この記事への評価にご協力をお願いします。
URLをクリックして、「ご協力ありがとうございました」のメッセージがご使用
のブラウザに表示されれば投票完了です。
良かった:
http://objectclub.esm.co.jp/cgi-bin/question.cgi?E002+2+0
普通:
http://objectclub.esm.co.jp/cgi-bin/question.cgi?E002+2+1
イマイチ:
http://objectclub.esm.co.jp/cgi-bin/question.cgi?E002+2+2
 
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━--■--●--■
■
┗編集後記

こんにちは、編集人です。
クリスマスセミナーで配布しました「オブジェクト倶楽部カレンダー」。オブ
ジェクト倶楽部:28号にて郵送希望者を募ったところ、みなさんから熱烈な要
望を多数いただきました。ありがとうございます。数に限りがあったため送付
できなかった方、ごめんなさい。そんなあなたに朗報です。オブジェクト倶楽
部カレンダーの電子データを公開します。ケースはありませんが印刷してお使
いください。なお、3月のカレンダーは、2月上旬に公開予定です。お楽しみに。
  1月:http://objectclub.esm.co.jp/calender/2004/1.pdf
  2月:http://objectclub.esm.co.jp/calender/2004/2.pdf
(さとみ)

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━--■--●--■
● ご意見、ご感想は         ⇒このメールに返信ください
〇 配信中止、アドレス変更は ⇒http://www.ObjectClub.jp/mlmagazine_help.html
〇 免責事項、過去の記事は   ⇒http://www.ObjectClub.jp/mlmagazine.html
■ 発行:オブジェクト倶楽部 ⇒http://www.ObjectClub.jp/
■ 編集代表:平鍋  健児
Copyright (c)2003-2004 オブジェクト倶楽部. All Rights Reserved.
powered by Eiwa System Management, Inc.