んだ日記

ndaDayoの技術日記です

PHPで『リファクタリング―プログラムの体質改善テクニック』を実装してみる (1)

リファクタリング―プログラムの体質改善テクニック』をphpで実装していきます。

リファクタリング 前のコード

ディレクトリ構成

App/
Movie.php
Rental.php
Customer.php

Movie.php

<?php

namespace App;

class Movie
{
    /** 一般向け
     *
     * @var int
     */
    const REGULAR = 0;

    /** 新着ビデオ
     *
     * @var int
     */
    const NEW_RELEASE = 1;

    /** 子供向け
     *
     * @var int
     */
    const CHILD = 2;

    /** @var string */
    private $title;

    /** @var int */
    private $priceCode;

    public function __construct($title,$priceCode)
    {
        $this->title = $title;
        $this->priceCode = $priceCode;
    }

    /**
     * @return string
     */
    public function getTitle()
    {
        return $this->title;
    }

    /**
     * @param string $title
     */
    public function setTitle($title)
    {
        $this->title = $title;
    }

    /**
     * @return int
     */
    public function getPriceCode()
    {
        return $this->priceCode;
    }

    /**
     * @param $arg
     */
    public function setPriceCode($arg)
    {
        $this->priceCode = $arg;
    }
}

Rental.php

<?php

namespace App;

class Rental
{
    /**
     * @var Movie
     */
    private $movie;

    /** @var int */
    private $dayRented;

    public function __construct(Movie $movie, $dayRented)
    {
        $this->movie = $movie;
        $this->dayRented = $dayRented;
    }

    /**
     * @return Movie
     */
    public function getMovie()
    {
        return $this->movie;
    }

    /**
     * @return int
     */
    public function getDaysRented()
    {
        return $this->dayRented;
    }
}

Customer.php

<?php

namespace App;

class Customer
{
    /** @var string */
    private $name;

    /** @var array */
    private $rental = [];

    public function __construct($name)
    {
        $this->name = $name;
    }

    /**
     * @param Rental $rental
     */
    public function addRental(Rental $rental)
    {
        $this->rental[] = $rental;
    }

    /**
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    public function statement()
    {
        $totalAmount = 0;
        $frequentRenterPoint = 0;

        $result = 'Rental Point for ' . $this->getName() . "\n";

        foreach ($this->rental as $rental) {
            $thisAmount = 0;
            switch ($rental->getMovie()->getPriceCode()) {
                case Movie::REGULAR:
                    $thisAmount += 2;
                    if ($rental->getDaysRented() > 2) {
                        $thisAmount += ($rental->getDaysRented() - 2) * 1.5;
                    }
                    break;
                case Movie::NEW_RELEASE:
                    $thisAmount += $rental->getDaysRented() * 3;
                    break;
                case Movie::CHILD:
                    $thisAmount += 1.5;
                    if ($rental->getDaysRented() > 3) {
                        $thisAmount += ($rental->getDaysRented() - 3) * 1.5;
                    }
                    break;
            }
            // レンタルポイントを加算する
            $frequentRenterPoint++;

            // 新作を2日以上借りた場合は、ボーナスポイント
            if (($rental->getMovie()->getPriceCode() === Movie::NEW_RELEASE) && $rental->getDaysRented() > 1) {
                $frequentRenterPoint++;
            }
            // 貸し出しに関する数値の表示
            $result .= "\t" . $rental->getMovie()->getTitle() . "\t" . $thisAmount . "\n";
            $totalAmount += $thisAmount;
        }
        $result .= 'Amount owed is ' . $totalAmount . "\n";
        $result .= 'You earned ' . $frequentRenterPoint . ' frequent renter points' . "\n";

        return $result;
    }
}