Los Techies : Blogs about software and anything tech!

Refactoring Day 13 : Extract Method Object


Today's refactoring comes from Martin Fowlers list of refactorings. You can find his original article here with a brief description.

This is a more infrequent refactoring that I see myself using but it comes in handy at times. When trying to apply an Extract Method refactoring, and multiple methods are needing to be introduced, it is sometimes gets ugly because of multiple local variables that are being used within a method. Because of this reason, it is better to introduce an Extract Method Object refactoring and to segregate the logic required to perform the task.

   1: public class OrderLineItem
   2: {
   3:     public decimal Price { get; private set; }
   4: }
   5:  
   6: public class Order
   7: {
   8:     private IList<OrderLineItem> OrderLineItems { get; set; }
   9:     private IList<decimal> Discounts { get; set; }
  10:     private decimal Tax { get; set; }
  11:  
  12:     public decimal Calculate()
  13:     {
  14:         decimal subTotal = 0m;
  15:  
  16:         // Total up line items
  17:         foreach (OrderLineItem lineItem in OrderLineItems)
  18:         {
  19:             subTotal += lineItem.Price;
  20:         }
  21:  
  22:         // Subtract Discounts
  23:         foreach (decimal discount in Discounts)
  24:             subTotal -= discount;
  25:  
  26:         // Calculate Tax
  27:         decimal tax = subTotal * Tax;
  28:  
  29:         // Calculate GrandTotal
  30:         decimal grandTotal = subTotal + tax;
  31:  
  32:         return grandTotal;
  33:     }
  34: }

This entails passing a reference to the class that will be returning the computation to a new object that has the multiple methods via the constructor, or passing the individual parameters to the constructor of the method object. I will be showing the former here.

   1: public class OrderLineItem
   2: {
   3:     public decimal Price { get; private set;}
   4: }
   5:  
   6: public class Order
   7: {
   8:     public IEnumerable<OrderLineItem> OrderLineItems { get; private set;}
   9:     public IEnumerable<decimal> Discounts { get; private set; }
  10:     public decimal Tax { get; private set; }
  11:  
  12:     public decimal Calculate()
  13:     {
  14:         return new OrderCalculator(this).Calculate();
  15:     }
  16: }
  17:  
  18: public class OrderCalculator
  19: {
  20:     private decimal SubTotal { get; set;}
  21:     private IEnumerable<OrderLineItem> OrderLineItems { get; set; }
  22:     private IEnumerable<decimal> Discounts { get; set; }
  23:     private decimal Tax { get; set; }
  24:  
  25:     public OrderCalculator(Order order)
  26:     {
  27:         OrderLineItems = order.OrderLineItems;
  28:         Discounts = order.Discounts;
  29:         Tax = order.Tax;
  30:     }
  31:  
  32:     public decimal Calculate()
  33:     {
  34:         CalculateSubTotal();
  35:  
  36:         SubtractDiscounts();
  37:  
  38:         CalculateTax();
  39:  
  40:         return SubTotal;
  41:     }
  42:  
  43:     private void CalculateSubTotal()
  44:     {
  45:         // Total up line items
  46:         foreach (OrderLineItem lineItem in OrderLineItems)
  47:             SubTotal += lineItem.Price;
  48:     }
  49:  
  50:     private void SubtractDiscounts()
  51:     {
  52:         // Subtract Discounts
  53:         foreach (decimal discount in Discounts)
  54:             SubTotal -= discount;
  55:     }
  56:  
  57:     private void CalculateTax()
  58:     {
  59:         // Calculate Tax
  60:         SubTotal += SubTotal * Tax;
  61:     }
  62: }

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 13 2009, 09:30 AM by schambers

Comments

Alastair Smith wrote re: Refactoring Day 13 : Extract Method Object
on 08-13-2009 11:19 AM

Good post.  But you've introduced a circular dependency between Order and OrderCalculator.  Would a static OrderCalculator class improve this?

Harry M wrote re: Refactoring Day 13 : Extract Method Object
on 08-13-2009 12:52 PM

Are you going to do the "Remove useless comments with same name as one line method" refactoring? :)

schambers wrote re: Refactoring Day 13 : Extract Method Object
on 08-13-2009 12:57 PM

@Alastair

Where is the circular dependency? An instance of Order is passed to the ctor of OrderCalculator.

on 08-13-2009 12:58 PM

Pluralsight On-Demand! I plan to have a full post on Pluralsight On- Demand! very soon. I became a subscriber recently and have found it to be an amazing training tool. Its just ike being in the classroom with the best instructors in the business and

Petar Petrov wrote re: Refactoring Day 13 : Extract Method Object
on 08-14-2009 11:47 AM

No not circular dependency but however I think Alastair Smith means that you don't have something like IOrderCalculator to be injected in the order so the order is always dependent on the concrete class OrderCalculator. ( return new OrderCalculator(this).Calculate() )

schambers wrote re: Refactoring Day 13 : Extract Method Object
on 08-14-2009 12:01 PM

Oh ok. that makes more sense. Yeah, OrderCalculator would be dependent on Order. You could easily just introduce an interface however the OrderCalculator is naturally going to have pretty intimate knowledge of how an order works.

张荣华 wrote 31天重构指南之十三:提取方法对象
on 09-29-2009 3:41 AM

这篇文章要说的重构来自于Martin Fowlwrs的重构列表,你可以在这里查看原始描述 这是一个不常用的重构。当你发现一个方法中存在过多的局部变量时,你可以通过使用“提取方法对象”重构来引入一些方...

bcmfqqymif wrote re: Refactoring Day 13 : Extract Method Object
on 10-02-2009 6:40 AM

ApD6bf  <a href="gijwqeouklwq.com/.../a>, [url=http://iyjzoawykcjx.com/]iyjzoawykcjx[/url], [link=http://ddbxmnwseolm.com/]ddbxmnwseolm[/link], http://hdwrwakshhzh.com/

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:01 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 ...

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