31
31 Days of Refactoring
31
31 2009 10 Sean Chambers blog
Tips
WPF
31 Tips
31 Sean
Chambers 31
http://www.lostechies.com/blogs/sean_chambers/archive/2009/07/31/31-days-of-refactoring.aspx
http://github.com/schambers/days-of-refactoring
Sean Chambers
1
2
3
1.
IList IList
using System.Collections.Generic;
namespace LosTechies.DaysOfRefactoring.EncapsulateCollection.Before
{
public class Order
{
private List _orderLines;
private double _orderTotal;
public IList OrderLines
{
get { return _orderLines; }
}
public void AddOrderLine(OrderLine orderLine)
{
_orderTotal += orderLine.Total;
_orderLines.Add(orderLine);
}
public void RemoveOrderLine(OrderLine orderLine)
{
orderLine = _orderLines.Find(o => o == orderLine);
if (orderLine == null)
return;
_orderTotal -= orderLine.Total;
_orderLines.Remove(orderLine);
}
}
public class OrderLine
{
public double Total { get; private set; }
}
}
IList IEnumerable IEnumerator GetEnumerator()
using System.Collections.Generic;
namespace LosTechies.DaysOfRefactoring.EncapsulateCollection.After
{
public class Order
{
private List _orderLines;
private double _orderTotal;
public IEnumerable OrderLines
{
get { return _orderLines; }
}
public void AddOrderLine(OrderLine orderLine)
{
_orderTotal += orderLine.Total;
_orderLines.Add(orderLine);
}
public void RemoveOrderLine(OrderLine orderLine)
{
orderLine = _orderLines.Find(o => o == orderLine);
if (orderLine == null)
return;
_orderTotal -= orderLine.Total;
_orderLines.Remove(orderLine);
}
}
public class OrderLine
{
public double Total { get; private set; }
}
}
SOA
2.
namespace LosTechies.DaysOfRefactoring.MoveMethod.Before
{
public class BankAccount
{
public BankAccount(int accountAge, int creditScore, AccountInterest accountInterest)
{
AccountAge = accountAge;
CreditScore = creditScore;
AccountInterest = accountInterest;
}
public int AccountAge { get; private set; }
public int CreditScore { get; private set; }
public AccountInterest { private set; }
4
public AccountInterest AccountInterest { get; private set; }
public double CalculateInterestRate()
{
if (CreditScore > 800)
return 0.02;
if (AccountAge > 10)
return 0.03;
return 0.05;
}
}
public class AccountInterest
{
public BankAccount Account { get; private set; }
public AccountInterest(BankAccount account)
{
Account = account;
}
public double InterestRate
{
get { return Account.CalculateInterestRate(); }
}
public bool IntroductoryRate
{
get { return Account.CalculateInterestRate() < 0.05; }
}
}
}
BankAccount CalculateInterestRate
namespace LosTechies.DaysOfRefactoring.MoveMethod.After
{
public class AccountInterest
{
public BankAccount Account { get; private set; }
public AccountInterest(BankAccount account)
{
Account = account;
}
public double InterestRate
{
get { return CalculateInterestRate(); }
}
public bool IntroductoryRate
{
get { return CalculateInterestRate() < 0.05; }
}
public double CalculateInterestRate()
{
if (Account.CreditScore > 800)
return 0.02;
if (Account.AccountAge > 10)
return 0.03;
return 0.05;
}
}
}
namespace LosTechies.DaysOfRefactoring.MoveMethod.After
{
public class BankAccount
{
public BankAccount(int accountAge, int creditScore, AccountInterest accountInterest)
{
AccountAge = accountAge;
CreditScore = creditScore;
AccountInterest = accountInterest;
}
public int AccountAge { get; private set; }
public int CreditScore { get; private set; }
public AccountInterest AccountInterest { get; private set; }
}
}
3.
Turn Car Motorcycle
Vehicle
namespace LosTechies.DaysOfRefactoring.PullUpMethod.Before
{
public abstract class Vehicle
{
// other methods
5
// other methods
}
public class Car : Vehicle
{
public void Turn(Direction direction)
{
// code here
}
}
public class Motorcycle : Vehicle
{
}
public enum Direction
{
Left,
Right
}
}
Car Motorcycle Turn
namespace LosTechies.DaysOfRefactoring.PullUpMethod.After
{
public abstract class Vehicle
{
public void Turn(Direction direction)
{
// code here
}
}
public class Car : Vehicle
{
}
public class Motorcycle : Vehicle
{
}
public enum Direction
{
Left,
Right
}
}
4.
Animal Bark Dog Dog
namespace LosTechies.DaysOfRefactoring.PushDownMethod.Before
{
public abstract class Animal
{
public void Bark()
{
// code to bark
}
}
public class Dog : Animal
{
}
public class Cat : Animal
{
}
}
Animal Bark Animal
namespace LosTechies.DaysOfRefactoring.PushDownMethod.After
{
public abstract class Animal
{
}
public class Dog : Animal
{
public void Bark()
{
// code to bark
}
}
public class Cat : Animal
{
}
}
5.
6
Account CheckingAccount SavingsAccount minimumCheckingBalance
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace LosTechies.DaysOfRefactoring.PullUpField.Before
{
public abstract class Account
{
}
public class CheckingAccount : Account
{
private decimal _minimumCheckingBalance = 5m;
}
public class SavingsAccount : Account
{
private decimal _minimumSavingsBalance = 5m;
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace LosTechies.DaysOfRefactoring.PullUpField.After
{
public abstract class Account
{
protected decimal _minimumBalance = 5m;
}
public class CheckingAccount : Account
{
}
public class SavingsAccount : Account
{
}
}
6.
Task _resolution BugTask BugTask
namespace LosTechies.DaysOfRefactoring.PushDownField.Before
{
public abstract class Task
{
protected string _resolution;
}
public class BugTask : Task
{
}
public class FeatureTask : Task
{
}
}
namespace LosTechies.DaysOfRefactoring.PushDownField.After
{
public abstract class Task
{
}
public class BugTask : Task
{
private string _resolution;
}
public class FeatureTask : Task
{
}
}
7.
namespace LosTechies.DaysOfRefactoring.Rename.Before
{
public class Person
{
public string FN { get; set; }
public decimal ClcHrlyPR()
{
// code to calculate hourly payrate
return 0m;
7
return 0m;
}
}
}
namespace LosTechies.DaysOfRefactoring.Rename.After
{
// Changed the class name to Employee
public class Employee
{
public string FirstName { get; set; }
public decimal CalculateHourlyPay()
{
// code to calculate hourly payrate
return 0m;
}
}
}
8.
Child Sanitation
namespace LosTechies.DaysOfRefactoring.ReplaceInheritance.Before
{
public class Sanitation
{
public string WashHands()
{
return "Cleaned!";
}
}
public class Child : Sanitation
{
}
}
Sanitation Child WashHands IOC
namespace LosTechies.DaysOfRefactoring.ReplaceInheritance.After
{
public class Sanitation
{
public string WashHands()
{
return "Cleaned!";
}
}
public class Child
{
private Sanitation Sanitation { get; set; }
public Child()
{
Sanitation = new Sanitation();
}
public string WashHands()
{
return Sanitation.WashHands();
}
}
}
9.
RegistrationProcessor ClassRegistration Create Total RegistrationProcessor
namespace LosTechies.DaysOfRefactoring.ExtractInterface.Before
{
public class ClassRegistration
{
public void Create()
{
// create registration code
}
public void Transfer()
{
// class transfer code
}
public decimal Total { get; private set; }
}
public class RegistrationProcessor
{
8
{
public decimal ProcessRegistration(ClassRegistration registration)
{
registration.Create();
return registration.Total;
}
}
}
IClassRegistration ClassRegistration RegistrationProcessor IClassRegistration
namespace LosTechies.DaysOfRefactoring.ExtractInterface.After
{
public interface IClassRegistration
{
void Create();
decimal Total { get; }
}
public class ClassRegistration : IClassRegistration
{
public void Create()
{
// create registration code
}
public void Transfer()
{
// class transfer code
}
public decimal Total { get; private set; }
}
public class RegistrationProcessor
{
public decimal ProcessRegistration(IClassRegistration registration)
{
registration.Create();
return registration.Total;
}
}
}
10.
CalculateGrandTotal subTotal subTotal discount Discounts
Tax
using System.Collections.Generic;
namespace LosTechies.DaysOfRefactoring.ExtractMethod.Before
{
public class Receipt
{
private IList Discounts { get; set; }
private IList ItemTotals { get; set; }
public decimal CalculateGrandTotal()
{
decimal subTotal = 0m;
foreach (decimal itemTotal in ItemTotals)
subTotal += itemTotal;
if (Discounts.Count > 0)
{
foreach (decimal discount in Discounts)
subTotal -= discount;
}
decimal tax = subTotal * 0.065m;
subTotal += tax;
return subTotal;
}
}
}
CalculateGrandTotal CalculateSubTotal CalculateDiscounts CalculateTax
using System.Collections.Generic;
namespace LosTechies.DaysOfRefactoring.ExtractMethod.After
{
public class Receipt
{
private IList Discounts { get; set; }
private IList ItemTotals { get; set; }
public decimal CalculateGrandTotal()
{
decimal subTotal = CalculateSubTotal();
subTotal = CalculateDiscounts(subTotal);
subTotal = CalculateTax(subTotal);
9
subTotal = CalculateTax(subTotal);
return subTotal;
}
private decimal CalculateTax(decimal subTotal)
{
decimal tax = subTotal * 0.065m;
subTotal += tax;
return subTotal;
}
private decimal CalculateDiscounts(decimal subTotal)
{
if (Discounts.Count > 0)
{
foreach (decimal discount in Discounts)
subTotal -= discount;
}
return subTotal;
}
private decimal CalculateSubTotal()
{
decimal subTotal = 0m;
foreach (decimal itemTotal in ItemTotals)
subTotal += itemTotal;
return subTotal;
}
}
}
11.
switch case if else
ClientCode State ShippingInfo
namespace LosTechies.DaysOfRefactoring.SwitchToStrategy.Before
{
public class ClientCode
{
public decimal CalculateShipping()
{
ShippingInfo shippingInfo = new ShippingInfo();
return shippingInfo.CalculateShippingAmount(State.Alaska);
}
}
public enum State
{
Alaska,
NewYork,
Florida
}
public class ShippingInfo
{
public decimal CalculateShippingAmount(State shipToState)
{
switch (shipToState)
{
case State.Alaska:
return GetAlaskaShippingAmount();
case State.NewYork:
return GetNewYorkShippingAmount();
case State.Florida:
return GetFloridaShippingAmount();
default:
return 0m;
}
}
private decimal GetAlaskaShippingAmount()
{
return 15m;
}
private decimal GetNewYorkShippingAmount()
{
return 10m;
}
private decimal GetFloridaShippingAmount()
{
return 3m;
}
}
}
IShippingCalculation ShippingInfo GetAlaskaShippingAmount GetNewYorkShippingAmount
10
GetFloridaShippingAmount IShippingCalculation IEnumerable
switch case IOC
using System;
using System.Collections.Generic;
using System.Linq;
namespace LosTechies.DaysOfRefactoring.SwitchToStrategy.After_WithIoC
{
public interface IShippingInfo
{
decimal CalculateShippingAmount(State state);
}
public class ClientCode
{
[Inject]
public IShippingInfo ShippingInfo { get; set; }
public decimal CalculateShipping()
{
return ShippingInfo.CalculateShippingAmount(State.Alaska);
}
}
public enum State
{
Alaska,
NewYork,
Florida
}
public class ShippingInfo : IShippingInfo
{
private IDictionary ShippingCalculations { get; set; }
public ShippingInfo(IEnumerable shippingCalculations)
{
ShippingCalculations = shippingCalculations.ToDictionary(calc => calc.State);
}
public decimal CalculateShippingAmount(State shipToState)
{
return ShippingCalculations[shipToState].Calculate();
}
}
public interface IShippingCalculation
{
State State { get; }
decimal Calculate();
}
public class AlaskShippingCalculation : IShippingCalculation
{
public State State { get { return State.Alaska; } }
public decimal Calculate()
{
return 15m;
}
}
public class NewYorkShippingCalculation : IShippingCalculation
{
public State State { get { return State.NewYork; } }
public decimal Calculate()
{
return 10m;
}
}
public class FloridaShippingCalculation : IShippingCalculation
{
public State State { get { return State.Florida; } }
public decimal Calculate()
{
return 3m;
}
}
}
12.
mock
namespace LosTechies.DaysOfRefactoring.BreakDependencies.Before
{
public class AnimalFeedingService
11
public class AnimalFeedingService
{
private bool FoodBowlEmpty { get; set; }
public void Feed()
{
if (FoodBowlEmpty)
Feeder.ReplenishFood();
// more code to feed the animal
}
}
public static class Feeder
{
public static void ReplenishFood()
{
// fill up bowl
}
}
}
mock IFeederService AnimalFeedingService
namespace LosTechies.DaysOfRefactoring.BreakDependencies.After
{
public class AnimalFeedingService
{
public IFeederService FeederService { get; set; }
public AnimalFeedingService(IFeederService feederService)
{
FeederService = feederService;
}
private bool FoodBowlEmpty { get; set; }
public void Feed()
{
if (FoodBowlEmpty)
FeederService.ReplenishFood();
// more code to feed the animal
}
}
public interface IFeederService
{
void ReplenishFood();
}
public class FeederService : IFeederService
{
public void ReplenishFood()
{
Feeder.ReplenishFood();
}
}
public static class Feeder
{
public static void ReplenishFood()
{
// fill up bowl
}
}
}
13.
Order Calculate
using System.Collections.Generic;
namespace LosTechies.DaysOfRefactoring.ExtractMethodObject.Before
{
public class OrderLineItem
{
public decimal Price { get; private set; }
}
public class Order
{
private IList OrderLineItems { get; set; }
private IList Discounts { get; set; }
private decimal Tax { get; set; }
public decimal Calculate()
{
decimal subTotal = 0m;
// Total up line items
foreach (OrderLineItem lineItem in OrderLineItems)
{
subTotal += lineItem.Price;
}
// Subtract Discounts
foreach (decimal discount in Discounts)
subTotal -= discount;
12
// Calculate Tax
decimal tax = subTotal * Tax;
// Calculate GrandTotal
decimal grandTotal = subTotal + tax;
return grandTotal;
}
}
}
OrderCalculator Order OrderCalculator Calculate
using System.Collections.Generic;
namespace LosTechies.DaysOfRefactoring.ExtractMethodObject.After
{
public class OrderLineItem
{
public decimal Price { get; private set; }
}
public class Order
{
public IEnumerable OrderLineItems { get; private set; }
public IEnumerable Discounts { get; private set; }
public decimal Tax { get; private set; }
public decimal Calculate()
{
return new OrderCalculator(this).Calculate();
}
}
public class OrderCalculator
{
private decimal SubTotal { get; set; }
private IEnumerable OrderLineItems { get; set; }
private IEnumerable Discounts { get; set; }
private decimal Tax { get; set; }
public OrderCalculator(Order order)
{
OrderLineItems = order.OrderLineItems;
Discounts = order.Discounts;
Tax = order.Tax;
}
public decimal Calculate()
{
CalculateSubTotal();
SubtractDiscounts();
CalculateTax();
return SubTotal;
}
private void CalculateSubTotal()
{
// Total up line items
foreach (OrderLineItem lineItem in OrderLineItems)
SubTotal += lineItem.Price;
}
private void SubtractDiscounts()
{
// Subtract Discounts
foreach (decimal discount in Discounts)
SubTotal -= discount;
}
private void CalculateTax()
{
// Calculate Tax
SubTotal += SubTotal * Tax;
}
}
}
14.
Video video rental
Customer
using System.Collections.Generic;
using System.Linq;
namespace LosTechies.DaysOfRefactoring.BreakResponsibilities.Before
{
13
{
public class Video
{
public void PayFee(decimal fee)
{
}
public void RentVideo(Video video, Customer customer)
{
customer.Videos.Add(video);
}
public decimal CalculateBalance(Customer customer)
{
returncustomer.LateFees.Sum();
}
}
public class Customer
{
public IList LateFees { get; set; }
public IList