表明の導入 (リファクタリング-p267)
リファクタリング
Published: 2019-03-01

目的

「リファクタリング」を理解するためにサンプルコードを PHP で書き換えてみました。

今回は「表明の導入」について書きます。

「表明の導入」 について

コードのある部分が、そのプログラムの状態について何らかの仮定を持っている。

実際、表明は本番コードにおいては取り除かれるのが普通です。

変更前

<?php

class Project
{
    public function getMemberExpenseLimit()
    {
        return 9999;
    }
}

class Employee
{
    const NULL_EXPENSE = -1.0;

    private $_expenseLimit = self::NULL_EXPENSE;
    private $_primaryProject;

    public function __construct()
    {
        $this->_primaryProject = new Project();
    }

    public function getExpenseLimit()
    {
        return ($this->_expenseLimit !== self::NULL_EXPENSE) ?
            $this->_expenseLimit : $this->_primaryProject->getMemberExpenseLimit();
    }

    public function getWithinLimit($expenseAmount)
    {
        return $expenseAmount <= $this->getExpenseLimit();
    }
}

$e = new Employee();
echo $e->getExpenseLimit() . "\n";

変更後

<?php

assert_options(ASSERT_CALLBACK, 'my_assert');

// 本番コード
assert_options(ASSERT_ACTIVE, false);

// 開発コード
// assert_options(ASSERT_ACTIVE, true);

class Project2
{
    public function getMemberExpenseLimit()
    {
        return 9999;
    }
}

class Employee2
{
    const NULL_EXPENSE = -1.0;

    private $_expenseLimit = self::NULL_EXPENSE;
    private $_primaryProject;

    public function __construct()
    {
        $this->_primaryProject = new Project2();
    }

    public function getExpenseLimit()
    {
        assert($this->_expenseLimit !== self::NULL_EXPENSE ||
            !is_null($this->_primaryProject));

        return ($this->_expenseLimit !== self::NULL_EXPENSE) ?
            $this->_expenseLimit : $this->_primaryProject->getMemberExpenseLimit();
    }

    public function getWithinLimit($expenseAmount)
    {
        return $expenseAmount <= $this->getExpenseLimit();
    }
}

function my_assert($file, $line, $code)
{
    echo 'file: ' . $file . "\n";
    echo 'line: ' . $line . "\n";
    echo 'code: ' . $code . "\n";
    throw new Exception();
};

$e2 = new Employee2();
echo $e2->getExpenseLimit() . "\n";