Design Patterns Reconsidered
-
Upload
alex-miller -
Category
Technology
-
view
113 -
download
1
description
Transcript of Design Patterns Reconsidered
![Page 1: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/1.jpg)
Design Patterns Reconsidered
Alex Miller@puredanger
![Page 2: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/2.jpg)
What is a Design Pattern?
“Each pattern describes a problem which occurs over and over again in our environment and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice.”
- Christopher Alexander
![Page 3: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/3.jpg)
![Page 4: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/4.jpg)
The Patterns Backlash
• Copy/paste
• Design by template
• Cookbook / recipe approach
“The Design Patterns solution is to turn the programmer into a fancy macro processor”
- M. J. Dominus, “Design Patterns” Aren't
![Page 5: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/5.jpg)
The Patterns Backlash
• Design patterns aren’t patterns
• Just workaround for missing language features
“At code level, most design patterns are code smells.”
- Stuart Halloway
![Page 6: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/6.jpg)
The Patterns Backlash
• Overuse
“Beginning developers never met a pattern or an object they didn’t like. Encouraging them to experiment with patterns is like throwing gasoline on a fire.”
- Jeff Atwood, Coding Horror
![Page 7: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/7.jpg)
...Reconsidered
Singleton
TemplateMethod
Visitor
Proxy
![Page 8: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/8.jpg)
Singleton
![Page 9: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/9.jpg)
+ getInstance() : Singleton- Singleton()+ foo() : Object
- INSTANCESingleton
There can be only one...
![Page 10: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/10.jpg)
Classic Singleton
![Page 11: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/11.jpg)
public final class Singleton {
Classic Singleton
![Page 12: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/12.jpg)
public final class Singleton { private static Singleton INSTANCE =
Classic Singleton
![Page 13: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/13.jpg)
public final class Singleton { private static Singleton INSTANCE = new Singleton();
Classic Singleton
![Page 14: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/14.jpg)
public final class Singleton { private static Singleton INSTANCE = new Singleton();
private Singleton() {}
Classic Singleton
![Page 15: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/15.jpg)
public final class Singleton { private static Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton instance() {
Classic Singleton
![Page 16: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/16.jpg)
public final class Singleton { private static Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton instance() { return INSTANCE;
Classic Singleton
![Page 17: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/17.jpg)
public final class Singleton { private static Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton instance() { return INSTANCE; }
Classic Singleton
![Page 18: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/18.jpg)
public final class Singleton { private static Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton instance() { return INSTANCE; }
public Object read() {
Classic Singleton
![Page 19: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/19.jpg)
public final class Singleton { private static Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton instance() { return INSTANCE; }
public Object read() { // nasty database call
Classic Singleton
![Page 20: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/20.jpg)
public final class Singleton { private static Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton instance() { return INSTANCE; }
public Object read() { // nasty database call }
Classic Singleton
![Page 21: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/21.jpg)
public final class Singleton { private static Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton instance() { return INSTANCE; }
public Object read() { // nasty database call }}
Classic Singleton
![Page 22: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/22.jpg)
public class Victim { public void something() { Object foo = Singleton.instance().read(); // etc... }}
Things go horribly wrong
![Page 23: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/23.jpg)
public class Victim { public void something() { Object foo = Singleton.instance().read(); // etc... }}
public class TestVictim { public void testSomething() { // Holy crap, how do I // mock the db call in Singleton? }}
Things go horribly wrong
![Page 24: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/24.jpg)
Singletons
Create
Coupling!
Hidden
![Page 25: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/25.jpg)
public interface Singleton { Object read();}
public class SingletonImpl implements Singleton {
public Object read() { // nasty database call return null; }}
Interfaces to the rescue
![Page 26: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/26.jpg)
public class Victim { private final Singleton singleton;
public Victim(Singleton singleton) { this.singleton = singleton; }
public void something() { Object foo = singleton.read(); // etc... }}
Dependency injection, you’re my hero!
![Page 27: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/27.jpg)
public class TestVictim {
public void testSomething() { Singleton s = new MockSingleton(); Victim victim = new Victim(s);
victim.something();
// assertions }}
Now we can test
![Page 28: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/28.jpg)
public class Component { private final Victim victim; public Component() { victim = new Victim( new SingletonImpl() ); }}
Push construction up
![Page 29: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/29.jpg)
Bubble
Up
Singletons
![Page 30: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/30.jpg)
Singleton
![Page 31: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/31.jpg)
What have we learned?
• Interfaces and dependency injection
• Reduce hidden coupling
• Allow testability
• Allow subclassing
• Make construction and use flexible
• If need only one, control by configuration
• Guice
• Spring
![Page 32: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/32.jpg)
...Reconsidered
Singleton
TemplateMethod
Visitor
Proxy
![Page 33: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/33.jpg)
Template Method
![Page 34: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/34.jpg)
Template Method
+ algorithm()# step1()# step2()# step3()
TemplateAlgorithmpublic void algorithm() { step1(); step2(); step3();}
# step1()# step2()# step3()
ConcreteAlgorithm1# step2()ConcreteAlgorithm2
![Page 35: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/35.jpg)
Spring MVC Controllers
Controller (interface)AbstractController AbstractUrlViewController UrlFilenameViewController BaseCommandController AbstractCommandController AbstractFormController AbstractWizardFormController SimpleFormController CancellableFormController MultiActionController ParameterizableViewController
![Page 36: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/36.jpg)
![Page 37: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/37.jpg)
“What we’ve got here is a failure to communicate....”
![Page 38: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/38.jpg)
public void algorithm() { step1Strategy.step1(); step2Strategy.step2(); step3Strategy.step3();}
+ step1()Step1Strategy
+ step2()Step2Strategy
+ step3()Step3Strategy
+ algorithm()
- Step1Strategy- Step2Strategy- Step3Strategy
TemplateAlgorithm
Refactoring to steps
![Page 39: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/39.jpg)
public void algorithm() { Context context = new Context(); step1Strategy.step1(context); step2Strategy.step2(context); step3Strategy.step3(context);}
+ step1(Context ctx)Step1Strategy
+ step2(Context ctx)Step2Strategy
+ step3(Context ctx)Step3Strategy
+ algorithm()
- Step1Strategy- Step2Strategy- Step3Strategy
TemplateAlgorithm
Context
Sharing context
![Page 40: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/40.jpg)
What have we learned?
• Prefer composition to inheritance
• Allows greater reuse
• Communicates intent better
• Easier to understand and maintain
• More robust as it evolves
• Inheritance is a very strong form of coupling
• Especially in a single-inheritance language
![Page 41: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/41.jpg)
...Reconsidered
Singleton
TemplateMethod
Visitor
Proxy
![Page 42: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/42.jpg)
operation1()operation2()
Node
operation1()operation2()
ConcreteNode1operation1()operation2()
CompositeNode
Composite hierarchy
![Page 43: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/43.jpg)
accept(NodeVisitor v)Node
accept(NodeVisitor v)ConcreteNode1
accept(NodeVisitor v)CompositeNode
visit(ConcreteNode1 n)visit(ConcreteNode2 n)...
NodeVisitor
visit(ConcreteNode1 n)visit(ConcreteNode2 n)...
ConcreteVisitor1visit(ConcreteNode1 n)visit(ConcreteNode2 n)...
ConcreteVisitor2
Visitor Pattern
![Page 44: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/44.jpg)
Navigation
![Page 45: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/45.jpg)
public class CompositeNode implements Visitable {
private List<Node> nodes; public void accept(NodeVisitor v) { v.visit(this); for(Node n : nodes) { v.visit(n); } }}
Internal Navigation
![Page 46: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/46.jpg)
public class CompositeNode { private List<Node> nodes; public void accept(NodeVisitor v) { v.visit(this);
List<Node> children = Navigation.getChildren(this);
for(Node n : children) { n.acceptVisitor(this); } }}
Navigation oracle
![Page 47: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/47.jpg)
visit(ConcreteNode1 n)visit(ConcreteNode2 n)...
NodeVisitor
visit(ConcreteNode1 n)visit(ConcreteNode2 n)...
ConcreteVisitor1visit(ConcreteNode1 n)visit(ConcreteNode2 n)...
ConcreteVisitor2
NavigationVisitor(NodeVisitor v)visit(ConcreteNode1 n)visit(ConcreteNode2 n)...
NavigationVisitor
Navigation Visitor
![Page 48: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/48.jpg)
Evolution
![Page 49: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/49.jpg)
accept(NodeVisitor v)Node
accept(NodeVisitor v)ConcreteNode1
accept(NodeVisitor v)CompositeNode
visit(ConcreteNode1 n)visit(ConcreteNode2 n)visit(NewNode n)...
NodeVisitor
visit(ConcreteNode1 n)visit(ConcreteNode2 n)visit(NewNode n)...
ConcreteVisitor1visit(ConcreteNode1 n)visit(ConcreteNode2 n)visit(NewNode n)...
ConcreteVisitor2
accept(NodeVisitor v)NewNode
![Page 50: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/50.jpg)
visit(ConcreteNode1 n)visit(ConcreteNode2 n)visit(NewNode n)...
NodeVisitor
visit(ConcreteNode1 n)visit(ConcreteNode2 n)visit(NewNode n)...
ConcreteVisitor1
visit(ConcreteNode1 n)visit(ConcreteNode2 n)visit(NewNode n)...
ConcreteVisitor2
visit(ConcreteNode1 n)visit(ConcreteNode2 n)visit(NewNode n)...
BaseVisitor
![Page 51: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/51.jpg)
Visitor Types
• “Collector” visitor - accumulate state
• “Finder” visitor - search and return
• “Event” visitor - stateless, fire events
• “Transform” visitor - modify while walking
• “Validation” visitor - validate and report
![Page 52: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/52.jpg)
public class FindVisitor implements ConcreteVisitor {
private final int seek; private Node match;
public FindVisitor(int seek) { this.seek = seek; } public Node getMatch() { return this.match; } public void visit(ConcreteNode1 n) { if( this.match == null && n.getValue() == seek) { this.match = n; } }}
Visitor abort
![Page 53: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/53.jpg)
public class ComputeVisitor implements ConcreteVisitor {
public void visit(ConcreteNode1 n) { try { // blah blah } catch(BadException e) { // what now? } }}
Exceptions
![Page 54: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/54.jpg)
What have we learned?
• Expression problem is tough
• Abstract base classes help plan for evolution
• Generics add precision and flexibility by revealing hidden coupling
![Page 55: Design Patterns Reconsidered](https://reader033.fdocuments.net/reader033/viewer/2022051412/54c6aed64a795938788b4570/html5/thumbnails/55.jpg)
Questions?
http://tech.puredanger.com/presentations/design-patterns-reconsidered