Top Banner
Andy Bulka Technical Director Austhink Software www.austhink.com March 2008 Refactoring to patterns…
13
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Extract Composite Talk Andy

Andy BulkaTechnical DirectorAusthink Softwarewww.austhink.com

March 2008

Refactoring to patterns…

Page 2: Extract Composite Talk Andy

Simple Composite patternClass with a “children” collectionChildren are of type Node (i.e. you point to

yourself)

Page 3: Extract Composite Talk Andy

Classic Composite pattern (GOF)Distinguish

between Composites and Leaves

Benefit of “classic” is that you can distinguish leafs and override display() or doubleClick() or whatever for leafs.

Page 4: Extract Composite Talk Andy

The Problem CodeWe have two

classes that loop through their children – duplicate code

The children attribute is named differently in both classes – inconsistent

Both classes are “composites”

Page 5: Extract Composite Talk Andy

The SolutionCreate a common base class which has the

generic “composite” looping behaviourThat’s where the name of the refactoring

comes from “Extract Composite”

Page 6: Extract Composite Talk Andy

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 = "" for node in self.allNodesVector: result += node.toPlainTextString() return result

class LinkTag(Node): def __init__(self): self.linkData = [] def toPlainTextString(self): result = "" for node in self.linkData: result += node.toPlainTextString() return result

f = FormTag()f.allNodesVector.append(Node("a"))f.allNodesVector.append(Node("b"))f.allNodesVector.append(Node("c"))

l = LinkTag()l.linkData += [Node("x"), Node("y"), Node("z")]

print f.toPlainTextString()print l.toPlainTextString()

abcxyz

output

Page 7: Extract Composite Talk Andy

Step 1# Create a Composite Class - compile

class Composite(Node): pass

Page 8: Extract Composite Talk Andy

Step 2Make each child container (a class in the hierarchy

thatcontains duplicate child-handling code) a subclass ofyour composite – compile

class Composite(Node): pass

class FormTag(Composite): ….class LinkTag(Composite): ….

Page 9: Extract Composite Talk Andy

Step 3For each method with duplicated looping code 1. move & rename the child reference field UP to the composite using "Pull Up Field" 2. Move the method UP to the composite using

"Pull Up Method" 3. Pull up any relevant constructor code too.

Page 10: Extract Composite Talk Andy

Everything moved to Compositeclass Composite(Node): def __init__(self): self.children = [] def toPlainTextString(self): result = "" for node in self.children: result += node.toPlainTextString() return result

class FormTag(Composite): pass class LinkTag(Composite): pass

Page 11: Extract Composite Talk Andy

Step 4Check interfaces so that client code using the

old composites still works.

f = FormTag()f.children.append(Node("a"))f.children.append(Node("b"))f.children.append(Node("c"))

l = LinkTag()l.children += [Node("x"), Node("y"), Node("z")]

print f.toPlainTextString()print l.toPlainTextString()

f = FormTag()f.allNodesVector.append(Node("a"))f.allNodesVector.append(Node("b"))f.allNodesVector.append(Node("c"))

l = LinkTag()l.linkData += [Node("x"), Node("y"), Node("z")]

print f.toPlainTextString()print l.toPlainTextString()

Page 12: Extract Composite Talk Andy

New UMLWe have inserted a

new class called Composite above the LinkTag and FormTag, which does the common looping work.

Page 13: Extract Composite Talk Andy

Before and After