Los Techies : Blogs about software and anything tech!

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: }

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: }

This is part of the 31 Days of Refactoring series. For a full list of Refactorings please see the original introductory post.

Kick It on DotNetKicks.com
Posted Aug 22 2009, 04:25 PM by schambers

Comments

cab wrote re: Refactoring Day 22 : Break Method
on 08-23-2009 9:35 PM

I think Kent Beck defines this as composed method pattern.

张荣华 wrote 31天重构指南之二十二:分解方法
on 10-16-2009 1:30 AM

今天要说的重构没有明确的出处,分解方法是我给它起的名字,我相信肯定还有别人做过类似的重构但却叫别一个名字,如果你在看完本文后觉得还有比“分解方法”更好的名字,请通知我。 分解重构是元重构的一种,所做...

31 Days of Refactoring « Vincent Leung's .NET Tech Clips wrote 31 Days of Refactoring &laquo; Vincent Leung&#039;s .NET Tech Clips
on 10-28-2009 9:28 AM

Pingback from  31 Days of Refactoring « Vincent Leung's .NET Tech Clips

PetterLiu wrote 31 Days of Refactoring
on 11-27-2009 4:02 AM

Refactoring Day 1 : Encapsulate Collection Refactoring Day 2 : Move Method Refactoring Day 3 : Pull ...

PetterLiu wrote 31 Days of Refactoring
on 11-27-2009 4:03 AM

Refactoring Day 1 : Encapsulate Collection Refactoring Day 2 : Move Method Refactoring Day 3 : Pull ...

Marek Rosa wrote re: Refactoring Day 22 : Break Method
on 02-18-2010 3:34 AM

I think that the refactored version is missing the loop over the products and also a product should be passed to SubtractDiscounts.

Add a Comment

(required)  
(optional)
(required)  
Remember Me?

Enter the numbers above:
Copyright Los Techies 2008, 2009. All rights reserved.
Powered by Community Server (Commercial Edition), by Telligent Systems