引数オブジェクトの導入 (リファクタリング-p295)
リファクタリング
Published: 2019-03-08

目的

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

今回は「引数オブジェクトの導入」について書きます。

「引数オブジェクトの導入」 について

本来まとめて扱うべき一連の引数がある。

このような引数群をオブジェクトにすることは、データをグループ化してまとめる点で価値があります。またこのリファクタリングは、引数リストを短くできる点でも有益です。

変更前

<?php

date_default_timezone_set('Asia/Tokyo');

class Entry
{
    private $_value;
    private $_chargeDate;

    public function __construct($value, DateTime $chargeDate)
    {
        $this->_value = $value;
        $this->_chargeDate = $chargeDate;
    }

    public function getDate()
    {
        return $this->_chargeDate;
    }

    public function getValue()
    {
        return $this->_value;
    }
}

class Account
{
    private $_entiries = [];

    public function __construct()
    {
        $e1 = new Entry(10, new DateTime('2018/10/14'));
        $e2 = new Entry(20, new DateTime('2018/10/18'));
        $e3 = new Entry(30, new DateTime('2018/10/20'));
        $e4 = new Entry(40, new DateTime('2018/10/23'));
        $e5 = new Entry(50, new DateTime('2018/11/14'));

        $this->_entiries = [
            $e1,
            $e2,
            $e3,
            $e4,
            $e5,
        ];
    }

    public function getFlowBetween(DateTime $start, DateTime $end)
    {
        $result = 0;
        foreach ($this->_entiries as $entry) {
            if ($entry->getDate()->getTimeStamp() >= $start->getTimeStamp() &&
                $entry->getDate()->getTimeStamp() <= $end->getTimeStamp()) {
                $result += $entry->getValue();
            }
        }

        return $result;
    }
}

$anAccount = new Account();
$startDate = new DateTime('2018/10/14');
$endDate = new DateTime('2018/10/20');
echo $anAccount->getFlowBetween($startDate, $endDate) . "\n";

変更後

<?php

date_default_timezone_set('Asia/Tokyo');

class Entry2
{
    private $_value;
    private $_chargeDate;

    public function __construct($value, DateTime $chargeDate)
    {
        $this->_value = $value;
        $this->_chargeDate = $chargeDate;
    }

    public function getDate()
    {
        return $this->_chargeDate;
    }

    public function getValue()
    {
        return $this->_value;
    }
}

class Account2
{
    private $_entiries = [];

    public function __construct()
    {
        $e1 = new Entry2(10, new DateTime('2018/10/14'));
        $e2 = new Entry2(20, new DateTime('2018/10/18'));
        $e3 = new Entry2(30, new DateTime('2018/10/20'));
        $e4 = new Entry2(40, new DateTime('2018/10/23'));
        $e5 = new Entry2(50, new DateTime('2018/11/14'));

        $this->_entiries = [
            $e1,
            $e2,
            $e3,
            $e4,
            $e5,
        ];
    }

    public function getFlowBetween(DateRange $range)
    {
        $result = 0;
        foreach ($this->_entiries as $entry) {
            if ($range->includes($entry->getDate())) {
                $result += $entry->getValue();
            }
        }

        return $result;
    }
}

class DateRange
{
    private $_start;
    private $_end;

    public function __construct(DateTime $start, DateTime $end)
    {
        $this->_start = $start;
        $this->_end = $end;
    }

    public function getStart()
    {
        return $this->_start;
    }

    public function getEnd()
    {
        return $this->_end;
    }

    public function includes(DateTime $arg)
    {
        return ($arg->getTimeStamp() >= $this->_start->getTimeStamp()) &&
            ($arg->getTimeStamp() <= $this->_end->getTimeStamp())
        ;
    }
}

$anAccount = new Account2();
$startDate = new DateTime('2018/10/14');
$endDate = new DateTime('2018/10/20');

$range = new DateRange($startDate, $endDate);
echo $anAccount->getFlowBetween($range) . "\n";