ソースをリファクタリングして、テンプレートパターンを適用する

オブ脳 in PHP

テンプレートパターン(2) テンプレートパターンの適用

ProEvo > PHP Evo > オブ脳 in PHP > テンプレートパターン (2) テンプレートパターンの適用

社長命令・起立プログラムをリファクタリングしてテンプレートパターンを適用する


1. リファクタリング
1.1 リファクタリングの目的
1.2 テストの利用
2. リファクタリングを行う
2.1 属性の追加およびコンストラクタのリファクタリング
2.2 属性"役職"を参照する
2.3 給料取得メソッドの追加
2.4 メソッドの移動
3. 実行

1. リファクタリング

1.1 リファクタリングの目的

本の中で説明しているようにテンプレートパターン(1)では社員クラスに似たような記述があります。これをリファクタリングしてシンプルでわかりやすいコードに変更します。

1.2 テストの利用

リファクタリングではプログラムの外部仕様は変わりません。つまり、テンプレートパターン(1)で作成したテストがそのまま使えます。
安全のために一つ変更したらテストを実行して、グリーンバーのままなのを確認しながら修正を行います。

2. リファクタリングを行う

2.1 属性の追加およびコンストラクタのリファクタリング

役職は各クラスで固定です。しかし、後のことを考えると属性にしておいて参照したほうが都合が良いです。そのため、属性に役職を追加します。
また、これらを社員クラスのコンストラクタで設定するように変更します。
ソースは次のようになります。

Shain.php
<?php
class Shain {
  var $name;      // 社員氏名
  var $kihonkyu;  // 基本給
  var $yakusyoku; // 役職

  function Shain($name, $kihonkyu, $yakusyoku)
  {
    $this->name = $name;
    $this->kihonkyu = $kihonkyu;
    $this->yakusyoku = $yakusyoku;
  }

  function standup()
  {
  }
}
?>
Tantou.php
<?php
require_once 'Shain.php';

class Tantou extends Shain {
  function Tantou($name, $kihonkyu)
  {
    $this->Shain($name, $kihonkyu, "担当");
  }

  function standup()
  {
    $out = "担当" . $this->name . "起立しました。";
    $out .= "給料は" . $this->kihonkyu . "円です。\n";
    return $out;
  }
}
?>
		
Shunin.php
<?php
require_once 'Shain.php';

class Shunin extends Shain {
  function Shunin($name, $kihonkyu)
  {
    $this->Shain($name, $kihonkyu, "主任");
  }

  function standup()
  {
    $kyuryou = $this->kihonkyu * 2 + 1;
    $out = "主任" . $this->name . "起立しました。";
    $out .= "給料は" . $kyuryou . "円です。\n";
    return $out;
  }
}
?>
Buchou.php
<?php
require_once 'Shain.php';

class Buchou extends Shain {
  function Buchou($name, $kihonkyu)
  {
    $this->Shain($name, $kihonkyu, "部長");
  }

  function standup()
  {
    $kyuryou = $this->kihonkyu * 3;
    $out = "部長" . $this->name . "起立しました。";
    $out .= "給料は" . $kyuryou . "円です。\n";
    return $out;
  }
}
?>
		
テストを実行します。下の画面のようにグリーンのバーならば修正は終了です。
[テスト結果]

2.2 属性"役職"を参照する

2.1で役職属性を追加したので、メソッドstandupでその属性を私用するように変更します。
ソースは次のようになります。

Tantou.php
<?php
require_once 'Shain.php';

class Tantou extends Shain {
  function Tantou($name, $kihonkyu)
  {
    $this->Shain($name, $kihonkyu, "担当");
  }

  function standup()
  {
    $out = $this->yakusyoku . $this->name . "起立しました。";
    $out .= "給料は" . $this->kihonkyu . "円です。\n";
    return $out;
  }
}
?>
		
Shunin.php
<?php
require_once 'Shain.php';

class Shunin extends Shain {
  function Shunin($name, $kihonkyu)
  {
    $this->Shain($name, $kihonkyu, "主任");
  }

  function standup()
  {
    $kyuryou = $this->kihonkyu * 2 + 1;
    $out = $this->yakusyoku . $this->name . "起立しました。";
    $out .= "給料は" . $kyuryou . "円です。\n";
    return $out;
  }
}
?>
		
Buchuo.php
<?php
require_once 'Shain.php';

class Buchou extends Shain {
  function Buchou($name, $kihonkyu)
  {
    $this->Shain($name, $kihonkyu, "部長");
  }

  function standup()
  {
    $kyuryou = $this->kihonkyu * 3;
    $out = $this->yakusyoku . $this->name . "起立しました。";
    $out .= "給料は" . $kyuryou . "円です。\n";
    return $out;
  }
}
?>
		
テストを実行します。下の画面のようにグリーンバーになれば変更は終了です。
[テスト結果]

2.3 給料取得メソッドの追加

給料を計算する処理をメソッドとして独立させます。メソッド"standup"を給料取得メソッドを使ってメッセージを作成するように変更します。
ソースは次のようになります。

Tantou.php
<?php
require_once 'Shain.php';

class Tantou extends Shain {
  function Tantou($name, $kihonkyu)
  {
    $this->Shain($name, $kihonkyu, "担当");
  }

  function getKyuryou()
  {
    return $this->kihonkyu;
  }

  function standup()
  {
    $out = $this->yakusyoku . $this->name . "起立しました。";
    $out .= "給料は" . $this->getKyuryou() . "円です。\n";
    return $out;
  }
}
?>
		
Shunin.php
<?php
require_once 'Shain.php';

class Shunin extends Shain {
  function Shunin($name, $kihonkyu)
  {
    $this->Shain($name, $kihonkyu, "主任");
  }

  function getKyuryou()
  {
    return ($this->kihonkyu * 2) + 1;
  }

  function standup()
  {
    $out = $this->yakusyoku . $this->name . "起立しました。";
    $out .= "給料は" . $this->getKyuryou() . "円です。\n";
    return $out;
  }
}
?>
		
Buchou.php
<?php
require_once 'Shain.php';

class Buchou extends Shain {
  function Buchou($name, $kihonkyu)
  {
    $this->Shain($name, $kihonkyu, "部長");
  }

  function getKyuryou()
  {
    return $this->kihonkyu * 3;
  }

  function standup()
  {
    $out = $this->yakusyoku . $this->name . "起立しました。";
    $out .= "給料は" . $this->getKyuryou() . "円です。\n";
    return $out;
  }
}
?>
		
テストを実行します。下の画面のようにグリーンバーになれば変更は終了です。
[テスト結果]

2.4 メソッドの移動

2.3の変更でstandupメソッドはどのクラスも同一の記述になりました。
そのためstandupメソッドを親クラスであるShainクラスに移動します。
ソースは次のようになります。

Shain.php
<?php
class Shain {
  var $name;      // 社員氏名
  var $kihonkyu;  // 基本給
  var $yakusyoku; // 役職

  function Shain($name, $kihonkyu, $yakusyoku)
  {
    $this->name = $name;
    $this->kihonkyu = $kihonkyu;
    $this->yakusyoku = $yakusyoku;
  }

  function standup()
  {
    $out = $this->yakusyoku . $this->name . "起立しました。";
    $out .= "給料は" . $this->getKyuryou() . "円です。\n";
    return $out;
  }
}
?>
		
Tantou.php
<?php
require_once 'Shain.php';

class Tantou extends Shain {
  function Tantou($name, $kihonkyu)
  {
    $this->Shain($name, $kihonkyu, "担当");
  }

  function getKyuryou()
  {
    return $this->kihonkyu;
  }
}
?>
		
Shunin.php
<?php
require_once 'Shain.php';

class Shunin extends Shain {
  function Shunin($name, $kihonkyu)
  {
    $this->Shain($name, $kihonkyu, "主任");
  }

  function getKyuryou()
  {
    return ($this->kihonkyu * 2) + 1;
  }
}
?>
		
Buchou.php
<?php
require_once 'Shain.php';

class Buchou extends Shain {
  function Buchou($name, $kihonkyu)
  {
    $this->Shain($name, $kihonkyu, "部長");
  }

  function getKyuryou()
  {
    return $this->kihonkyu * 3;
  }
}
?>
		
テストを実行します。下の画面のようにグリーンバーになれば修正は完了です。
[テスト結果]

3. 実行

プログラムを実行します。下の画面のようになれば成功です。
[実行結果] [デモ]
以上で変更は終了です。


$Revision: 1 $
Last update: $Date: 2009-03-19 20:17:04 +0900 (譛ィ, 19 3譛 2009) $