んだ日記

ndaDayoの技術日記です

PHPで『リファクタリング―プログラムの体質改善テクニック』を実装してみる (4) メソッドの抽出と問い合わせによる一時変数の置き換え

前回の記事

nda-desu.hatenablog.com

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

<?php

namespace App;

class Customer
{
   
    ~省略~

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

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

        foreach ($this->rentals as $rental) {

            $frequentRenterPoint++;
            if (($rental->getMovie()->getPriceCode() === Movie::NEW_RELEASE) && $rental->getDaysRented() > 1) {
                $frequentRenterPoint++;
            }
            // 貸し出しに関する数値の表示
            $result .= "\t" . $rental->getMovie()->getTitle() . "\t" . $rental->getCharge() . "\n";
            $totalAmount += $rental->getCharge();
        }
        $result .= 'Amount owed is ' . $totalAmount . "\n";
        $result .= 'You earned ' . $frequentRenterPoint . ' frequent renter points' . "\n";

        return $result;
    }
}

メソッドの抽出と移動

メソッドの抽出を行うのは、以下の箇所

$frequentRenterPoint++;
if (($rental->getMovie()->getPriceCode() === Movie::NEW_RELEASE) && $rental->getDaysRented() > 1) {
$frequentRenterPoint++;
}

この部分は、Rentalクラスに移動させる

Rental.php

<?php 
namespace App;

use App\Movie;

class Rental
{
   
 ~省略~
    /**
     * 新作を2日以上借りた場合は、ボーナスポイント
     *
     * @return int
     */
    public function getFrequentRentalPoint()
    {
        if (($this->getMovie()->getPriceCode() === Movie::NEW_RELEASE) && $this->getDaysRented() > 1) {
            return $frequentRentalPoints = 2;
        } else {
            return $frequentRentalPoints = 1;
        }
    }
}

Customer.php

<?php

namespace App;

use  App\Rental;

class Customer
{
    ~省略~    

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

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

        foreach ($this->rentals as $rental) {

            $frequentRentalPoints = $rental->getFrequentRentalPoint();
         
            $result .= "\t" . $rental->getMovie()->getTitle() . "\t" . $rental->getCharge() . "\n";
            $totalAmount += $rental->getCharge();
        }
        $result .= 'Amount owed is ' . $totalAmount . "\n";
        $result .= 'You earned ' . $frequentRentalPoints . ' frequent renter points' . "\n";

        return $result;
    }

}

これでメソッドの抽出は終わりました。

残りは、一時変数の置き換えです。

問い合わせによる一時変数の置き換え

問い合わせによる一時変数の置き換えとは?

一時変数へのすべての参照を新たなメソッドに置き換える。 新たなメソッドが他のメソッドでも使えるようになる。

サンプル

 $basePrice = $quantity + $itemPrice;
    
    if($basePrice > 1000){
      return $basePrice * 0.95;    
    }else{
    return $basePrice * 0.98; 
    }


// ↓のように修正すること

  if($basePrice > 1000){
      return basePrice() * 0.95;    
    }else{
    return basePrice() * 0.98; 
    }

   function basePrice(){
     return $quantity + $itemPrice;
   }

問い合わせによる一時変数の置き換え実装

置き換えを行うのは

$frequentRentalPoints = $rental->getFrequentRentalPoint();

$rental->getCharge()

この部分。

Customer.php

<?php 

    /**
     * @return string
     */
    public function statement()
    {
        $result = 'Rental Point for ' . $this->getName() . "\n";

        foreach ($this->rentals as $rental) {
            $result .= "\t" . $rental->getMovie()->getTitle() . "\t" . $this->getTotalCharge() . "\n";
        }
        $result .= 'Amount owed is ' . $this->getTotalCharge() . "\n";
        $result .= 'You earned ' . $this->getTotalFrequentRentalPoint() . ' frequent renter points' . "\n";

        return $result;
    }

    /**
     * @return int
     */
    private function getTotalCharge()
    {
        $result = 0;
        foreach ($this->rentals as $rental) {
            $result += $rental->getCharge();
        }
        return $result;
    }

    /**
     * @return int
     */
    private function getTotalFrequentRentalPoint()
    {
        $result = 0;
        foreach ($this->rentals as $rental) {
            $result += $rental->getFrequentRentalPoint();
        }
        return $result;
    }

以上。