Refactoring Day 22 : Break Method
Today’s refactoring didn’t really come from any one source. It just named it although someone else may have something similar that’s named differently. If you know of anyone that has a name for this other than Break Method, please let me know.
This refactoring is kind of a meta-refactoring in the fact that it’s just extract method applied over and over until you decompose one large method into several smaller methods. This example here is a tad contrived because the AcceptPayment method isn’t doing as much as I wanted. Imagine that there is much more supporting code around each action that the one method is doing. That would match a real world scenario if you can picture it that way.
Below we have the AcceptPayment method that can be decomposed multiple times into distinct methods.
1: public class CashRegister
2: {
3: public CashRegister()
4: {
5: Tax = 0.06m;
6: }
7:
8: private decimal Tax { get; set; }
9:
10: public void AcceptPayment(Customer customer, IEnumerable<Product> products, decimal payment)
11: {
12: decimal subTotal = 0m;
13: foreach (Product product in products)
14: {
15: subTotal += product.Price;
16: }
17:
18: foreach(Product product in products)
19: {
20: subTotal -= product.AvailableDiscounts;
21: }
22:
23: decimal grandTotal = subTotal * Tax;
24:
25: customer.DeductFromAccountBalance(grandTotal);
26: }
27: }
28:
29: public class Customer
30: {
31: public void DeductFromAccountBalance(decimal amount)
32: {
33: // deduct from balance
34: }
35: }
36:
37: public class Product
38: {
39: public decimal Price { get; set; }
40: public decimal AvailableDiscounts { get; set; }
41: }
</div> </div>
As you can see the AcceptPayment method has a couple of things that can be decomposed into targeted methods. So we perform the Extract Method refactoring a number of times until we come up with the result:
1: public class CashRegister
2: {
3: public CashRegister()
4: {
5: Tax = 0.06m;
6: }
7:
8: private decimal Tax { get; set; }
9: private IEnumerable<Product> Products { get; set; }
10:
11: public void AcceptPayment(Customer customer, IEnumerable<Product> products, decimal payment)
12: {
13: decimal subTotal = CalculateSubtotal();
14:
15: subTotal = SubtractDiscounts(subTotal);
16:
17: decimal grandTotal = AddTax(subTotal);
18:
19: SubtractFromCustomerBalance(customer, grandTotal);
20: }
21:
22: private void SubtractFromCustomerBalance(Customer customer, decimal grandTotal)
23: {
24: customer.DeductFromAccountBalance(grandTotal);
25: }
26:
27: private decimal AddTax(decimal subTotal)
28: {
29: return subTotal * Tax;
30: }
31:
32: private decimal SubtractDiscounts(decimal subTotal)
33: {
34: foreach(Product product in Products)
35: {
36: subTotal -= product.AvailableDiscounts;
37: }
38: return subTotal;
39: }
40:
41: private decimal CalculateSubtotal()
42: {
43: decimal subTotal = 0m;
44: foreach (Product product in Products)
45: {
46: subTotal += product.Price;
47: }
48: return subTotal;
49: }
50: }
51:
52: public class Customer
53: {
54: public void DeductFromAccountBalance(decimal amount)
55: {
56: // deduct from balance
57: }
58: }
59:
60: public class Product
61: {
62: public decimal Price { get; set; }
63: public decimal AvailableDiscounts { get; set; }
64: }
</div> </div>
This is part of the 31 Days of Refactoring series. For a full list of Refactorings please see the original introductory post.