株式会社エス・スリー・フォー

C++/C#/VB.NETによる リファクタリング – リファクタリング前(C++)

Movie.h

#ifndef __MOVIE_H__
#define __MOVIE_H__

#include <string>

class Movie {
public:
  enum price_code { 
    CHILDRENS = 2,
    REGULAR = 0,
    NEW_RELEASE = 1
  };

  Movie(std::string title, price_code priceCode);
  price_code getPriceCode() const;
  void setPriceCode(price_code arg);
  std::string getTitle() const;

private:
  std::string _title;
  price_code  _priceCode;

};

#endif

Movie.cpp

#include "Movie.h"

Movie::Movie(std::string title, price_code priceCode) 
  : _title(title), _priceCode(priceCode) {
}

Movie::price_code Movie::getPriceCode() const {
  return _priceCode;
}

void Movie::setPriceCode(price_code arg) {
  _priceCode = arg;
}

std::string Movie::getTitle() const {
  return _title;
}

Rental.h

#ifndef __RENTAL_H__
#define __RENTAL_H__

class Movie;

class Rental {
public:
  Rental(Movie* movie, int daysRented);
  int getDaysRented() const;
  const Movie* getMovie() const;

private:
  Movie* _movie;
  int _daysRented;

};

#endif

Rental.cpp

#include "Rental.h"

Rental::Rental(Movie* movie, int daysRented) : _movie(movie), _daysRented(daysRented) {
}

int Rental::getDaysRented() const {
  return _daysRented;
}

const Movie* Rental::getMovie() const {
  return _movie;
}

Customer.h

#ifndef __CUSTOMER_H__
#define __CUSTOMER_H__

#include <vector>
#include <string>

class Rental;

class Customer {
public:
  explicit Customer(std::string name);
  void addRental(Rental* arg);
  std::string getName() const;
  std::string statement(double& amount, int& point) const;
  std::string statement() const;

private:
  std::string _name;
  std::vector<Rental*> _rentals;

};

inline std::string Customer::statement() const {
  double amount;
  int point;
  return statement(amount,point);
}

#endif

Customer.cpp

#include <sstream>

#include "Customer.h"
#include "Rental.h"
#include "Movie.h"

Customer::Customer(std::string name) : _name(name) {
}

void Customer::addRental(Rental* arg) {
  _rentals.push_back(arg);
}

std::string Customer::getName() const {
  return _name;
}

std::string Customer::statement(double& totalAmount, int& frequentRenterPoints) const {
  totalAmount = 0;
  frequentRenterPoints = 0;
  std::ostringstream result;
  result << "Rental Record for " << getName() << "\n";
  for ( std::vector<Rental*>::const_iterator rentals = _rentals.begin();
        rentals != _rentals.end(); ++rentals ) {
    double thisAmount = 0;
    const Rental* each = *rentals;
    // 一行ごとに金額を計算
    switch ( each->getMovie()->getPriceCode() ) {
    case Movie::REGULAR :
      thisAmount += 2;
      if ( each->getDaysRented() > 2 )
        thisAmount += (each->getDaysRented() - 2) * 1.5;
      break;
    case Movie::NEW_RELEASE :
      thisAmount += each->getDaysRented() * 3;
      break;
    case Movie::CHILDRENS :
      thisAmount += 1.5;
      if ( each->getDaysRented() > 3 )
        thisAmount += (each->getDaysRented() - 3) * 1.5;
      break;
    }
    // レンタルポイントを加算
    frequentRenterPoints++;
    // 新作を二日以上借りた場合はボーナスポイント
    if ( (each->getMovie()->getPriceCode() == Movie::NEW_RELEASE) &&
         each->getDaysRented() > 1 )
      frequentRenterPoints++;
    // この貸し出しに対する数値の表示
    result << "\t" << each->getMovie()->getTitle() << "\t"
           <<  thisAmount << "\n";
    totalAmount += thisAmount;
  }
  // フッタ部分の追加
  result << "Amount owed is " << totalAmount << "\n"
         << "You earned " << frequentRenterPoints << " frequent renter points";
  return result.str();
}