今回は、こちらの『Java言語で学ぶリファクタリング入門』をPHPで書いていきます。
第一回は
『シンボリック定数によるマジックナンバーの置き換え』
です。
マジックナンバーを書いてはいけない理由
マジックナンバーとは?
プログラム中に直接埋め込まれた数値。
例)
if(input.length() < 100){ .. }
書いた人にしかわからない、書いた人も忘れてしまう謎数字。
それがマジックナンバー
マジックナンバーを書いてはいけない理由
①意味がわかりにくい
その数字が何を意味しているのかわからないので解読に手間がかかる。。
②修正しにくい
たとえば、100文字が200文字になったら....
if(input.length() < 100){ .. }
100は、他にも使われているかもしれないから一発置換できない。。
リファクタリング前
サンプルは、コマンドを与えてRobotを動かすというプログラム
・コマンドが0なら、歩く
・コマンドが1なら、止まる
・コマンドが2なら、ジャンプ
コマンドがマジックナンバーで書かれているコードがこちら。
<?php namespace App; class Robot { /** @var string */ public $name; /** * Robot constructor. * * @param $name */ public function __construct(String $name) { $this->name = $name; } /** * * @return string * @param $command */ public function order(int $command) { if ($command === 0) { return $this->name . 'が歩く' . "\n"; } elseif ($command === 1) { return $this->name . 'は止まる' . "\n"; } elseif ($command === 2 { return $this->name . 'がジャンプする' . "\n"; } else { return $command . 'のコマンドはないですよ' . "\n"; } } }
使ってみる
<?php // index.php use App\Robot; $robot = new Robot('パンティーロボ'); echo $robot->order(0); // 歩く echo $robot->order(1); // 止まる echo $robot->order(2); // ジャンプ // 実行結果 パンティーロボが歩く パンティーロボは止まる パンティーロボがジャンプする
$robot->order(0);
は意味がわからないので、コメントで説明しています。
リファクタリング
シンボリック定数によるマジックナンバーの置き換え
<?php namespace App; class Robot { const COMMAND_WALK = 0; const COMMAND_STOP = 1; const COMMAND_JUMP = 2; ~省略~ /** * * @return string * @param $command */ public function order(int $command) { if ($command === Robot::COMMAND_WALK) { return $this->name . 'が歩く' . "\n"; } elseif ($command === Robot::COMMAND_STOP) { return $this->name . 'は止まる' . "\n"; } elseif ($command === Robot::COMMAND_JUMP) { return $this->name . 'がジャンプする' . "\n"; } else { return $command . 'のコマンドはないですよ' . "\n"; } } }
<?php use App\Robot; $robot = new Robot('パンティーロボ'); echo $robot->order(Robot::COMMAND_WALK); echo $robot->order(Robot::COMMAND_STOP); echo $robot->order(Robot::COMMAND_JUMP);
テスト
テストも書いてみました。
<?php namespace Tests; use App\Robot; use PHPUnit_Framework_TestCase; class RobotTest extends PHPUnit_Framework_TestCase { const Exception = 3; /** * @var Robot */ protected $robot; protected function setUp() { $this->robot = new Robot("テストロボット"); } /** * @test * */ public function testOrder() { $expected_walk = 'テストロボットが歩く' . "\n"; $expected_stop = 'テストロボットは止まる'. "\n"; $expected_jump = 'テストロボットがジャンプする'. "\n"; $expected_exception = RobotTest::Exception . 'のコマンドはないですよ' . "\n"; $this->assertEquals($expected_walk, $this->robot->order(Robot::COMMAND_WALK)); $this->assertEquals($expected_stop, $this->robot->order(Robot::COMMAND_STOP)); $this->assertEquals($expected_jump, $this->robot->order(Robot::COMMAND_JUMP)); $this->assertEquals($expected_exception, $this->robot->order(RobotTest::Exception)); } }
vendor/bin/phpunit tests/ PHPUnit 5.7.27 by Sebastian Bergmann and contributors. . 1 / 1 (100%) Time: 448 ms, Memory: 4.00MB OK (1 test, 4 assertions)
以上。