Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Extract Composite Talk Andy

  • Be the first to comment

  • Be the first to like this

Extract Composite Talk Andy

  1. 1. Andy Bulka Technical Director Austhink Software www.austhink.com March 2008 Refactoring to patterns…
  2. 2. Simple Composite pattern <ul><li>Class with a “children” collection </li></ul><ul><li>Children are of type Node (i.e. you point to yourself) </li></ul>
  3. 3. Classic Composite pattern (GOF) <ul><li>Distinguish between Composites and Leaves </li></ul><ul><li>Benefit of “classic” is that you can distinguish leafs and override display() or doubleClick() or whatever for leafs. </li></ul>
  4. 4. The Problem Code <ul><li>We have two classes that loop through their children – duplicate code </li></ul><ul><li>The children attribute is named differently in both classes – inconsistent </li></ul><ul><li>Both classes are “composites” </li></ul>
  5. 5. The Solution <ul><li>Create a common base class which has the generic “composite” looping behaviour </li></ul><ul><li>That’s where the name of the refactoring comes from “Extract Composite” </li></ul>
  6. 6. Original Problem code class Node (object): def __init__(self, name): self.name = name def toPlainTextString (self): return self.name class FormTag (Node): def __init__(self): self.allNodesVector = [] def toPlainTextString (self): result = &quot;&quot; for node in self.allNodesVector: result += node.toPlainTextString() return result class LinkTag (Node): def __init__(self): self.linkData = [] def toPlainTextString (self): result = &quot;&quot; for node in self.linkData: result += node.toPlainTextString() return result f = FormTag() f.allNodesVector.append(Node(&quot;a&quot;)) f.allNodesVector.append(Node(&quot;b&quot;)) f.allNodesVector.append(Node(&quot;c&quot;)) l = LinkTag() l.linkData += [Node(&quot;x&quot;), Node(&quot;y&quot;), Node(&quot;z&quot;)] print f.toPlainTextString() print l.toPlainTextString() abc xyz output
  7. 7. Step 1 <ul><li># Create a Composite Class - compile </li></ul><ul><li>class Composite(Node): </li></ul><ul><li>pass </li></ul>
  8. 8. Step 2 <ul><li>Make each child container (a class in the hierarchy that </li></ul><ul><li>contains duplicate child-handling code) a subclass of </li></ul><ul><li>your composite – compile </li></ul><ul><li>class Composite(Node): </li></ul><ul><li>pass </li></ul><ul><li>class FormTag(Composite): </li></ul><ul><li>… . </li></ul><ul><li>class LinkTag(Composite): </li></ul><ul><li>… . </li></ul>
  9. 9. Step 3 <ul><li>For each method with duplicated looping code </li></ul><ul><li>1. move & rename the child reference field UP </li></ul><ul><li>to the composite using &quot;Pull Up Field&quot; </li></ul><ul><li>2. Move the method UP to the composite using &quot;Pull Up Method&quot; </li></ul><ul><li>3. Pull up any relevant constructor code too. </li></ul>
  10. 10. Everything moved to Composite <ul><li>class Composite (Node): </li></ul><ul><li>def __init__(self): </li></ul><ul><li>self.children = [] </li></ul><ul><li>def toPlainTextString(self): </li></ul><ul><li>result = &quot;&quot; </li></ul><ul><li>for node in self.children: </li></ul><ul><li>result += node.toPlainTextString() </li></ul><ul><li>return result </li></ul><ul><li>class FormTag(Composite): </li></ul><ul><li>pass </li></ul><ul><li>class LinkTag(Composite): </li></ul><ul><li>pass </li></ul>
  11. 11. Step 4 <ul><li>Check interfaces so that client code using the old composites still works. </li></ul>f = FormTag() f. children .append(Node(&quot;a&quot;)) f. children .append(Node(&quot;b&quot;)) f. children .append(Node(&quot;c&quot;)) l = LinkTag() l. children += [Node(&quot;x&quot;), Node(&quot;y&quot;), Node(&quot;z&quot;)] print f.toPlainTextString() print l.toPlainTextString() f = FormTag() f. allNodesVector .append(Node(&quot;a&quot;)) f. allNodesVector .append(Node(&quot;b&quot;)) f. allNodesVector .append(Node(&quot;c&quot;)) l = LinkTag() l. linkData += [Node(&quot;x&quot;), Node(&quot;y&quot;), Node(&quot;z&quot;)] print f.toPlainTextString() print l.toPlainTextString()
  12. 12. New UML <ul><li>We have inserted a new class called Composite above the LinkTag and FormTag, which does the common looping work. </li></ul>
  13. 13. Before and After

×