Source: http://jczeus.com/refac_cpp.html from "Refactoring; Improving the Design of Existing Code by Martin Fowler
The VideoStore.cpp was created so you have a working example
that can be tested.
Refactoring Example:
VideoStove.cpp - main routine that works in .NET C++
Movie.h Movie.cpp
Rental.h Rental.cpp
Customer.h Customer.cpp
// VideoStore.cpp : Defines the entry point for the console application.
#include "Customer.h"
#include "Movie.h"
#include "Rental.h"
#include
using std::endl;
using std::cout;
int main(int argc, char* argv[])
{
Customer bob("Robert Andrews");
Movie bambi("Bambi", Movie::CHILDRENS);
Movie lucas("Star Wars", Movie::NEW_RELEASE);
Movie classic("The African Queen", Movie::REGULAR);
Rental weekend( lucas, 2);
Rental week( bambi, 5);
Rental overnight( classic, 1);
bob.addRental( weekend );
bob.addRental( week );
bob.addRental( overnight );
cout << bob.statement() << endl;
return 0;
}
// Movie.h
#ifndef MOVIE_H
#define MOVIE_H
#include
class Movie {
public:
static const int CHILDRENS = 2;
static const int REGULAR = 0;
static const int NEW_RELEASE = 1;
Movie( const std::string& title, int priceCode = REGULAR );
int getPriceCode() const;
void setPriceCode( int arg );
std::string getTitle() const;
private:
std::string _title;
int _priceCode;
};
inline Movie::
Movie( const std::string& title, int priceCode )
: _title( title )
, _priceCode( priceCode )
{}
inline int Movie::
getPriceCode() const { return _priceCode; }
inline void Movie::
setPriceCode( int arg ) { _priceCode = arg; }
inline std::string Movie::
getTitle() const { return _title; }
#endif // MOVIE_H
// Movie.cpp
#include "Movie.h"
// Rental.h
#ifndef RENTAL_H
#define RENTAL_H
#include "Movie.h"
class Rental {
public:
Rental( const Movie& movie, int daysRented );
int getDaysRented() const;
Movie & getMovie();
private:
Movie _movie;
int _daysRented;
};
inline Rental::
Rental( const Movie& movie, int daysRented )
: _movie( movie )
, _daysRented( daysRented ) {}
inline int Rental::
getDaysRented() const { return _daysRented; }
inline Movie & Rental::getMovie() {
return _movie;
}
#endif // RENTAL_H
// Rental.cpp
// Customer.h
#ifndef CUSTOMER_H
#define CUSTOMER_H
#include
#include
#include "Rental.h"
class Customer {
public:
Customer();
explicit Customer( const std::string& name );
void addRental( const Rental& arg );
std::string getName() const;
std::string statement();
private:
std::string _name;
std::vector< Rental > _rentals;
};
inline Customer::Customer() {}
inline Customer::Customer( const std::string& name )
: _name( name ) {}
inline void Customer::addRental( const Rental& arg ) {
_rentals.push_back( arg );
}
inline std::string Customer::
getName() const { return _name; }
#endif // CUSTOMER_H
// Customer.cpp
#include
#include
#include "Customer.h"
using namespace std;
// using std::ostringstream;
// using std::vector;
string Customer::statement() {
double totalAmount = 0;
int frequentRenterPoints = 0;
vector< Rental >::iterator iter = _rentals.begin();
vector< Rental >::iterator iter_end = _rentals.end();
ostringstream result;
result << "Rental Record for " << getName() << "\n";
for ( ; iter != iter_end; ++iter ) {
double thisAmount = 0;
Rental each = *iter;
// determine amounts for each line
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;
}
// add frequent renter points
frequentRenterPoints++;
// add bonus for a two day new release rental
if ( ( each.getMovie().getPriceCode() == Movie::NEW_RELEASE )
&& each.getDaysRented() > 1 ) frequentRenterPoints++;
// show figures for this rental
result << "\t" << each.getMovie().getTitle() << "\t"
<< thisAmount << "\n";
totalAmount += thisAmount;
}
// add footer lines
result << "Amount owed is " << totalAmount << "\n";
result << "You earned " << frequentRenterPoints
<< " frequent renter points";
return result.str();
}