oday’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: } 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:
31 Days of Refactoring Sean Chambers 36
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: }
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: } 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:
31 Days of Refactoring Sean Chambers 36
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: }