Thursday, December 23, 2010

How CSharp design patterns and refactoring differ from other languages - Part 02

This post continuing the post "How CSharp design patterns and refactoring differ from other languages - Part 01" and is based on Martin Fowler's "Refactoring" book.

For the refactoring explanation, please read the book, Marting Fowler explains it much better than I'll ever could. I'll concentrate of how it is done in CSharp.

So the first refactoring action in the book is "Extract Method" ( select the code from "double thidAmount = 0" till the end of the switch block, Menu --> Refactor --> Extract Method )
The automatic Extract-Method saves you the human errors such as double Vs. int, Yet - You always needed to test it and verify that the automation did what you expected it to do.

Next - renaming "each" to "aRental" (Not that I like this naming convention, but it is better than "each" and is is soon going away) and "thisAmount" --> "result"

And Moving Customer.AmountFor(Rental aRental) to Rental.GetCharge()
* You are missing the middle step - since I struggled with blogger editor html Vs WYSIWYG modes and lost some of the versions and my patience
---
using System.Collections;
using System.Collections.Generic;

namespace Refactoring
{
public class Customer
{
public string Name { get; private set; }
List _rentals = new List();

public Customer(string name)
{
Name = name;
}

public void AddRental(Rental rental)
{
_rentals.Add(rental);
}

public string Statement()
{
double totalAmount = 0;
int FrequentRenterPoints = 0;
IEnumerable rentals = _rentals;
string result = "Rental Record for " + Name + "\n";

foreach (Rental each in rentals)
{
double thisAmount = each.GetCharge();
// Add frequent renter points
FrequentRenterPoints++;
if (each.Movie.PriceCode == Movie.NEW_RELEASE &&
each.DaysRented > 1)
FrequentRenterPoints++;

// show figures for this rental
result += "\t" + each.Movie.Title + "\t" + thisAmount + "\n";
totalAmount += thisAmount;
}

// add footer
result += "Amount owed is " + totalAmount + "\n";
result += "You earned " + FrequentRenterPoints + " frequent renter points";

return result;
}
}
}
---

namespace Refactoring
{
public class Rental
{
public Movie Movie { get; private set; }
public int DaysRented { get; private set; }

public Rental(Movie movie, int daysRented)
{
Movie = movie;
DaysRented = daysRented;
}

public double GetCharge()
{
double result = 0;

// Determine amount for each line
switch (Movie.PriceCode)
{
case Movie.REGULAR:
result += 2;
if (DaysRented > 2)
result += (DaysRented - 2) * 1.5;
break;
case Movie.NEW_RELEASE:
result += DaysRented * 3;
break;
case Movie.CHILDRENS:
result += 1.5;
if (DaysRented > 3)
result += (DaysRented - 3) * 1.5;
break;
}

return result;
}
}
}
---

No comments: