単方向関連の双方向への変更 (リファクタリング-p197)
リファクタリング
Published: 2018-12-08

目的

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

今回は「単方向関連の双方向への変更」について書きます。

「単方向関連の双方向への変更」 について

2つのクラスが互いにその特性を使う必要があるが、単方向のリンクしかない。

このイディオムは、これでいいと思えるまで何度もテストしなければならないので、扱いにくいと思います。

変更前

<?php

class Order
{
    /* @var Customer */
    public $_customer;

    public function getCustomer()
    {
        return $this->_customer;
    }

    public function setCustomer(Customer $customer)
    {
        $this->_customer = $customer;
    }
}

class Customer
{
}

$c = new Customer();
$o = new Order();
$o->setCustomer($c);

echo get_class($o->getCustomer()) . "\n";

変更後

<?php

class Order2
{
    /* @var Customer2 */
    public $_customer;

    public function getCustomer()
    {
        return $this->_customer;
    }

    public function setCustomer(Customer2 $customer)
    {
        if (!is_null($this->_customer)) {
            // このコードは動かない 擬似コード
            // $this->_customer->friendOrders()->remove($this);
        }
        $this->_customer = $customer;
        if (!is_null($this->_customer)) {
            // このコードは動かない 擬似コード
            // $this->_customer->friendOrders()->add($this);
        }
    }
}

class Customer2
{
    private $_orders = [];

    public function friendOrders()
    {
        // 関連を変更するときは、Orderオブジェクトだけがこれを使うこと
        return $this->_orders;
    }
}
$c = new Customer2();
$o = new Order2();
$o->setCustomer($c);

echo get_class($o->getCustomer()) . "\n";