SlideShare une entreprise Scribd logo
1  sur  55
Télécharger pour lire hors ligne
Design Patterns
 Reconsidered




     Alex Miller
    @puredanger
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
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
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
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
...Reconsidered

      Template     Visitor
      Method
                          Proxy
Singleton
Singleton
There can be only one...

                Singleton
    - INSTANCE
    + getInstance() : Singleton
    - Singleton()
    + foo() : Object
Classic Singleton
Classic Singleton
public final class Singleton {
Classic Singleton
public final class Singleton {
  private static Singleton INSTANCE =
Classic Singleton
public final class Singleton {
  private static Singleton INSTANCE =
    new Singleton();
Classic Singleton
public final class Singleton {
  private static Singleton INSTANCE =
    new Singleton();

  private Singleton() {}
Classic Singleton
public final class Singleton {
  private static Singleton INSTANCE =
    new Singleton();

  private Singleton() {}

  public static Singleton instance() {
Classic Singleton
public final class Singleton {
  private static Singleton INSTANCE =
    new Singleton();

  private Singleton() {}

  public static Singleton instance() {
    return INSTANCE;
Classic Singleton
public final class Singleton {
  private static Singleton INSTANCE =
    new Singleton();

  private Singleton() {}

 public static Singleton instance() {
   return INSTANCE;
 }
Classic Singleton
public final class Singleton {
  private static Singleton INSTANCE =
    new Singleton();

  private Singleton() {}

 public static Singleton instance() {
   return INSTANCE;
 }

  public Object read() {
Classic Singleton
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
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
public final class Singleton {
  private static Singleton INSTANCE =
    new Singleton();

    private Singleton() {}

    public static Singleton instance() {
      return INSTANCE;
    }

    public Object read() {
      // nasty database call
    }
}
Things go horribly wrong
public class Victim {
  public void something() {
    Object foo = Singleton.instance().read();
    // etc...
  }
}
Things go horribly wrong
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?
  }
}
Create


                          Hidden
Singletons




                      Coupling!
Interfaces to the rescue
public interface Singleton {
  Object read();
}

public class SingletonImpl
  implements Singleton {

    public Object read() {
      // nasty database call
      return null;
    }
}
Dependency injection,
        you’re my hero!
public class Victim {
  private final Singleton singleton;

    public Victim(Singleton singleton) {
      this.singleton = singleton;
    }

    public void something() {
      Object foo = singleton.read();
      // etc...
    }
}
Now we can test
public class TestVictim {

    public void testSomething() {
      Singleton s = new MockSingleton();
      Victim victim = new Victim(s);

        victim.something();

        // assertions
    }
}
Push construction up
public class Component {
  private final Victim victim;

    public Component() {
      victim = new Victim(
        new SingletonImpl() );
    }
}
Up


             Bubble

Singletons
Singleton
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
...Reconsidered

       Template        Visitor
       Method
                              Proxy
Singleton
Template Method
Template Method

                                      public void algorithm() {
              TemplateAlgorithm         step1();
             + algorithm()              step2();
             # step1()                  step3();
             # step2()                }
             # step3()




ConcreteAlgorithm1        ConcreteAlgorithm2
# step1()                 # step2()
# step2()
# step3()
Spring MVC
        Controllers
Controller (interface)
   AbstractController
     AbstractUrlViewController
       UrlFilenameViewController
     BaseCommandController
       AbstractCommandController
       AbstractFormController
          AbstractWizardFormController
          SimpleFormController
            CancellableFormController
     MultiActionController
     ParameterizableViewController
“What we’ve got
here is a failure to
communicate....”
Refactoring to steps
                                      Step1Strategy
                                  + step1()
              TemplateAlgorithm
             - Step1Strategy
                                      Step2Strategy
             - Step2Strategy
                                  + step2()
             - Step3Strategy
             + algorithm()
                                      Step3Strategy
                                  + step3()




public void algorithm() {
  step1Strategy.step1();
  step2Strategy.step2();
  step3Strategy.step3();
}
Sharing context
                                         Step1Strategy
                                     + step1(Context ctx)
                 TemplateAlgorithm
                - Step1Strategy
                                         Step2Strategy
                - Step2Strategy
                                     + step2(Context ctx)
                - Step3Strategy
                + algorithm()
                                         Step3Strategy
                                     + step3(Context ctx)




public void algorithm() {
                                            Context
  Context context = new Context();
  step1Strategy.step1(context);
  step2Strategy.step2(context);
  step3Strategy.step3(context);
}
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
...Reconsidered

       Template        Visitor
       Method
                              Proxy
Singleton
Composite hierarchy
                     Node
                 operation1()
                 operation2()



 ConcreteNode1                  CompositeNode
 operation1()                   operation1()
 operation2()                   operation2()
Visitor Pattern
                           Node
                   accept(NodeVisitor v)



        ConcreteNode1             CompositeNode
      accept(NodeVisitor v)     accept(NodeVisitor v)




                         NodeVisitor
                  visit(ConcreteNode1 n)
                  visit(ConcreteNode2 n)
                  ...



      ConcreteVisitor1                ConcreteVisitor2
visit(ConcreteNode1 n)          visit(ConcreteNode1 n)
visit(ConcreteNode2 n)          visit(ConcreteNode2 n)
...                             ...
N
 av
    iga
          tio
             n
Internal Navigation
public class CompositeNode
  implements Visitable {

    private List<Node> nodes;
    public void accept(NodeVisitor v) {
      v.visit(this);
      for(Node n : nodes) {
        v.visit(n);
      }
    }
}
Navigation oracle
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 Visitor
                         NodeVisitor
                  visit(ConcreteNode1 n)
                  visit(ConcreteNode2 n)
                  ...



      ConcreteVisitor1                 ConcreteVisitor2
visit(ConcreteNode1 n)           visit(ConcreteNode1 n)
visit(ConcreteNode2 n)           visit(ConcreteNode2 n)
...                              ...




                    NavigationVisitor
          NavigationVisitor(NodeVisitor v)
          visit(ConcreteNode1 n)
          visit(ConcreteNode2 n)
          ...
Evo
      lutio
           n
Node
                   accept(NodeVisitor v)



        ConcreteNode1             CompositeNode
      accept(NodeVisitor v)     accept(NodeVisitor v)


                        NewNode
                   accept(NodeVisitor v)




                         NodeVisitor
                  visit(ConcreteNode1 n)
                  visit(ConcreteNode2 n)
                  visit(NewNode n)
                  ...



    ConcreteVisitor1                ConcreteVisitor2
visit(ConcreteNode1 n)          visit(ConcreteNode1 n)
visit(ConcreteNode2 n)          visit(ConcreteNode2 n)
visit(NewNode n)                visit(NewNode n)
...                             ...
NodeVisitor
                visit(ConcreteNode1 n)
                visit(ConcreteNode2 n)
                visit(NewNode n)
                ...


                        BaseVisitor
                 visit(ConcreteNode1 n)
                 visit(ConcreteNode2 n)
                 visit(NewNode n)
                 ...



    ConcreteVisitor1                 ConcreteVisitor2
visit(ConcreteNode1 n)           visit(ConcreteNode1 n)
visit(ConcreteNode2 n)           visit(ConcreteNode2 n)
visit(NewNode n)                 visit(NewNode n)
...                              ...
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
Visitor abort
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;
Exceptions
public class ComputeVisitor
  implements ConcreteVisitor {

    public void visit(ConcreteNode1 n) {
      try {
        // blah blah
      } catch(BadException e) {
        // what now?
      }
    }
}
What have we learned?
• Expression problem is tough
• Abstract base classes help plan for evolution
• Generics add precision and flexibility by
  revealing hidden coupling
Questions?




http://tech.puredanger.com/
   presentations/design-
   patterns-reconsidered

Contenu connexe

Tendances

Backbone.js: Run your Application Inside The Browser
Backbone.js: Run your Application Inside The BrowserBackbone.js: Run your Application Inside The Browser
Backbone.js: Run your Application Inside The BrowserHoward Lewis Ship
 
Use of Apache Commons and Utilities
Use of Apache Commons and UtilitiesUse of Apache Commons and Utilities
Use of Apache Commons and UtilitiesPramod Kumar
 
[2019-07] GraphQL in depth (serverside)
[2019-07] GraphQL in depth (serverside)[2019-07] GraphQL in depth (serverside)
[2019-07] GraphQL in depth (serverside)croquiscom
 
FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6Dmitry Soshnikov
 
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Domenic Denicola
 
#살아있다 #자프링외길12년차 #코프링2개월생존기
#살아있다 #자프링외길12년차 #코프링2개월생존기#살아있다 #자프링외길12년차 #코프링2개월생존기
#살아있다 #자프링외길12년차 #코프링2개월생존기Arawn Park
 
Xlab #1: Advantages of functional programming in Java 8
Xlab #1: Advantages of functional programming in Java 8Xlab #1: Advantages of functional programming in Java 8
Xlab #1: Advantages of functional programming in Java 8XSolve
 
Solid Software Design Principles
Solid Software Design PrinciplesSolid Software Design Principles
Solid Software Design PrinciplesJon Kruger
 
«Objective-C Runtime в примерах» — Алексей Сторожев, e-Legion
«Objective-C Runtime в примерах» — Алексей Сторожев, e-Legion«Objective-C Runtime в примерах» — Алексей Сторожев, e-Legion
«Objective-C Runtime в примерах» — Алексей Сторожев, e-Legione-Legion
 
Reactive Access to MongoDB from Scala
Reactive Access to MongoDB from ScalaReactive Access to MongoDB from Scala
Reactive Access to MongoDB from ScalaHermann Hueck
 
Advanced JavaScript Concepts
Advanced JavaScript ConceptsAdvanced JavaScript Concepts
Advanced JavaScript ConceptsNaresh Kumar
 
Introduction to Clean Code
Introduction to Clean CodeIntroduction to Clean Code
Introduction to Clean CodeJulio Martinez
 
Reactive Access to MongoDB from Java 8
Reactive Access to MongoDB from Java 8Reactive Access to MongoDB from Java 8
Reactive Access to MongoDB from Java 8Hermann Hueck
 
Http4s, Doobie and Circe: The Functional Web Stack
Http4s, Doobie and Circe: The Functional Web StackHttp4s, Doobie and Circe: The Functional Web Stack
Http4s, Doobie and Circe: The Functional Web StackGaryCoady
 
Building High Perf Web Apps - IE8 Firestarter
Building High Perf Web Apps - IE8 FirestarterBuilding High Perf Web Apps - IE8 Firestarter
Building High Perf Web Apps - IE8 FirestarterMithun T. Dhar
 
Dart London hackathon
Dart  London hackathonDart  London hackathon
Dart London hackathonchrisbuckett
 

Tendances (20)

Backbone.js: Run your Application Inside The Browser
Backbone.js: Run your Application Inside The BrowserBackbone.js: Run your Application Inside The Browser
Backbone.js: Run your Application Inside The Browser
 
Use of Apache Commons and Utilities
Use of Apache Commons and UtilitiesUse of Apache Commons and Utilities
Use of Apache Commons and Utilities
 
Headless Js Testing
Headless Js TestingHeadless Js Testing
Headless Js Testing
 
[2019-07] GraphQL in depth (serverside)
[2019-07] GraphQL in depth (serverside)[2019-07] GraphQL in depth (serverside)
[2019-07] GraphQL in depth (serverside)
 
SOLID PRINCIPLES
SOLID PRINCIPLESSOLID PRINCIPLES
SOLID PRINCIPLES
 
FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6
 
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
 
The IoC Hydra
The IoC HydraThe IoC Hydra
The IoC Hydra
 
#살아있다 #자프링외길12년차 #코프링2개월생존기
#살아있다 #자프링외길12년차 #코프링2개월생존기#살아있다 #자프링외길12년차 #코프링2개월생존기
#살아있다 #자프링외길12년차 #코프링2개월생존기
 
Xlab #1: Advantages of functional programming in Java 8
Xlab #1: Advantages of functional programming in Java 8Xlab #1: Advantages of functional programming in Java 8
Xlab #1: Advantages of functional programming in Java 8
 
Solid Software Design Principles
Solid Software Design PrinciplesSolid Software Design Principles
Solid Software Design Principles
 
«Objective-C Runtime в примерах» — Алексей Сторожев, e-Legion
«Objective-C Runtime в примерах» — Алексей Сторожев, e-Legion«Objective-C Runtime в примерах» — Алексей Сторожев, e-Legion
«Objective-C Runtime в примерах» — Алексей Сторожев, e-Legion
 
Reactive Access to MongoDB from Scala
Reactive Access to MongoDB from ScalaReactive Access to MongoDB from Scala
Reactive Access to MongoDB from Scala
 
Advanced JavaScript Concepts
Advanced JavaScript ConceptsAdvanced JavaScript Concepts
Advanced JavaScript Concepts
 
Introduction to Clean Code
Introduction to Clean CodeIntroduction to Clean Code
Introduction to Clean Code
 
Reactive Access to MongoDB from Java 8
Reactive Access to MongoDB from Java 8Reactive Access to MongoDB from Java 8
Reactive Access to MongoDB from Java 8
 
Magic methods
Magic methodsMagic methods
Magic methods
 
Http4s, Doobie and Circe: The Functional Web Stack
Http4s, Doobie and Circe: The Functional Web StackHttp4s, Doobie and Circe: The Functional Web Stack
Http4s, Doobie and Circe: The Functional Web Stack
 
Building High Perf Web Apps - IE8 Firestarter
Building High Perf Web Apps - IE8 FirestarterBuilding High Perf Web Apps - IE8 Firestarter
Building High Perf Web Apps - IE8 Firestarter
 
Dart London hackathon
Dart  London hackathonDart  London hackathon
Dart London hackathon
 

Similaire à Design Patterns Reconsidered

2. Design patterns. part #2
2. Design patterns. part #22. Design patterns. part #2
2. Design patterns. part #2Leonid Maslov
 
RxJava и Android. Плюсы, минусы, подводные камни
RxJava и Android. Плюсы, минусы, подводные камниRxJava и Android. Плюсы, минусы, подводные камни
RxJava и Android. Плюсы, минусы, подводные камниStfalcon Meetups
 
The Ring programming language version 1.7 book - Part 85 of 196
The Ring programming language version 1.7 book - Part 85 of 196The Ring programming language version 1.7 book - Part 85 of 196
The Ring programming language version 1.7 book - Part 85 of 196Mahmoud Samir Fayed
 
Deuce STM - CMP'09
Deuce STM - CMP'09Deuce STM - CMP'09
Deuce STM - CMP'09Guy Korland
 
Reactive programming on Android
Reactive programming on AndroidReactive programming on Android
Reactive programming on AndroidTomáš Kypta
 
Design pattern - part 3
Design pattern - part 3Design pattern - part 3
Design pattern - part 3Jieyi Wu
 
Kotlin / Android Update
Kotlin / Android UpdateKotlin / Android Update
Kotlin / Android UpdateGarth Gilmour
 
Processing large-scale graphs with Google(TM) Pregel by MICHAEL HACKSTEIN at...
 Processing large-scale graphs with Google(TM) Pregel by MICHAEL HACKSTEIN at... Processing large-scale graphs with Google(TM) Pregel by MICHAEL HACKSTEIN at...
Processing large-scale graphs with Google(TM) Pregel by MICHAEL HACKSTEIN at...Big Data Spain
 
Design patterns with kotlin
Design patterns with kotlinDesign patterns with kotlin
Design patterns with kotlinAlexey Soshin
 
10 Typical Enterprise Java Problems
10 Typical Enterprise Java Problems10 Typical Enterprise Java Problems
10 Typical Enterprise Java ProblemsEberhard Wolff
 
Decoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICDecoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICKonstantin Kudryashov
 
Processing large-scale graphs with Google(TM) Pregel
Processing large-scale graphs with Google(TM) PregelProcessing large-scale graphs with Google(TM) Pregel
Processing large-scale graphs with Google(TM) PregelArangoDB Database
 
Frank Celler – Processing large-scale graphs with Google(TM) Pregel - NoSQL m...
Frank Celler – Processing large-scale graphs with Google(TM) Pregel - NoSQL m...Frank Celler – Processing large-scale graphs with Google(TM) Pregel - NoSQL m...
Frank Celler – Processing large-scale graphs with Google(TM) Pregel - NoSQL m...NoSQLmatters
 
Session #6 loaders and adapters
Session #6  loaders and adaptersSession #6  loaders and adapters
Session #6 loaders and adaptersVitali Pekelis
 
Java Concurrency Gotchas
Java Concurrency GotchasJava Concurrency Gotchas
Java Concurrency GotchasAlex Miller
 
TDD and mobile development: some forgotten techniques, illustrated with Android
TDD and mobile development: some forgotten techniques, illustrated with AndroidTDD and mobile development: some forgotten techniques, illustrated with Android
TDD and mobile development: some forgotten techniques, illustrated with AndroidCodemotion
 

Similaire à Design Patterns Reconsidered (20)

2. Design patterns. part #2
2. Design patterns. part #22. Design patterns. part #2
2. Design patterns. part #2
 
RxJava и Android. Плюсы, минусы, подводные камни
RxJava и Android. Плюсы, минусы, подводные камниRxJava и Android. Плюсы, минусы, подводные камни
RxJava и Android. Плюсы, минусы, подводные камни
 
The Ring programming language version 1.7 book - Part 85 of 196
The Ring programming language version 1.7 book - Part 85 of 196The Ring programming language version 1.7 book - Part 85 of 196
The Ring programming language version 1.7 book - Part 85 of 196
 
Deuce STM - CMP'09
Deuce STM - CMP'09Deuce STM - CMP'09
Deuce STM - CMP'09
 
Reactive programming on Android
Reactive programming on AndroidReactive programming on Android
Reactive programming on Android
 
Design pattern - part 3
Design pattern - part 3Design pattern - part 3
Design pattern - part 3
 
Test Engine
Test EngineTest Engine
Test Engine
 
Kotlin / Android Update
Kotlin / Android UpdateKotlin / Android Update
Kotlin / Android Update
 
Devoxx 2012 (v2)
Devoxx 2012 (v2)Devoxx 2012 (v2)
Devoxx 2012 (v2)
 
Processing large-scale graphs with Google(TM) Pregel by MICHAEL HACKSTEIN at...
 Processing large-scale graphs with Google(TM) Pregel by MICHAEL HACKSTEIN at... Processing large-scale graphs with Google(TM) Pregel by MICHAEL HACKSTEIN at...
Processing large-scale graphs with Google(TM) Pregel by MICHAEL HACKSTEIN at...
 
Design patterns with kotlin
Design patterns with kotlinDesign patterns with kotlin
Design patterns with kotlin
 
Test Engine
Test EngineTest Engine
Test Engine
 
10 Typical Enterprise Java Problems
10 Typical Enterprise Java Problems10 Typical Enterprise Java Problems
10 Typical Enterprise Java Problems
 
Decoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICDecoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DIC
 
Processing large-scale graphs with Google(TM) Pregel
Processing large-scale graphs with Google(TM) PregelProcessing large-scale graphs with Google(TM) Pregel
Processing large-scale graphs with Google(TM) Pregel
 
Frank Celler – Processing large-scale graphs with Google(TM) Pregel - NoSQL m...
Frank Celler – Processing large-scale graphs with Google(TM) Pregel - NoSQL m...Frank Celler – Processing large-scale graphs with Google(TM) Pregel - NoSQL m...
Frank Celler – Processing large-scale graphs with Google(TM) Pregel - NoSQL m...
 
Session #6 loaders and adapters
Session #6  loaders and adaptersSession #6  loaders and adapters
Session #6 loaders and adapters
 
Object-oriented Basics
Object-oriented BasicsObject-oriented Basics
Object-oriented Basics
 
Java Concurrency Gotchas
Java Concurrency GotchasJava Concurrency Gotchas
Java Concurrency Gotchas
 
TDD and mobile development: some forgotten techniques, illustrated with Android
TDD and mobile development: some forgotten techniques, illustrated with AndroidTDD and mobile development: some forgotten techniques, illustrated with Android
TDD and mobile development: some forgotten techniques, illustrated with Android
 

Plus de Alex Miller

Clojure/West Overview (12/1/11)
Clojure/West Overview (12/1/11)Clojure/West Overview (12/1/11)
Clojure/West Overview (12/1/11)Alex Miller
 
Concurrent Stream Processing
Concurrent Stream ProcessingConcurrent Stream Processing
Concurrent Stream ProcessingAlex Miller
 
Stream Execution with Clojure and Fork/join
Stream Execution with Clojure and Fork/joinStream Execution with Clojure and Fork/join
Stream Execution with Clojure and Fork/joinAlex Miller
 
Cracking clojure
Cracking clojureCracking clojure
Cracking clojureAlex Miller
 
Releasing Relational Data to the Semantic Web
Releasing Relational Data to the Semantic WebReleasing Relational Data to the Semantic Web
Releasing Relational Data to the Semantic WebAlex Miller
 
Clojure: The Art of Abstraction
Clojure: The Art of AbstractionClojure: The Art of Abstraction
Clojure: The Art of AbstractionAlex Miller
 
Tree Editing with Zippers
Tree Editing with ZippersTree Editing with Zippers
Tree Editing with ZippersAlex Miller
 
Groovy concurrency
Groovy concurrencyGroovy concurrency
Groovy concurrencyAlex Miller
 
Innovative Software
Innovative SoftwareInnovative Software
Innovative SoftwareAlex Miller
 
Scaling Your Cache
Scaling Your CacheScaling Your Cache
Scaling Your CacheAlex Miller
 
Caching In The Cloud
Caching In The CloudCaching In The Cloud
Caching In The CloudAlex Miller
 
Scaling Your Cache And Caching At Scale
Scaling Your Cache And Caching At ScaleScaling Your Cache And Caching At Scale
Scaling Your Cache And Caching At ScaleAlex Miller
 
Marshmallow Test
Marshmallow TestMarshmallow Test
Marshmallow TestAlex Miller
 
Strange Loop Conference 2009
Strange Loop Conference 2009Strange Loop Conference 2009
Strange Loop Conference 2009Alex Miller
 
Scaling Hibernate with Terracotta
Scaling Hibernate with TerracottaScaling Hibernate with Terracotta
Scaling Hibernate with TerracottaAlex Miller
 
Project Fortress
Project FortressProject Fortress
Project FortressAlex Miller
 
Java Collections API
Java Collections APIJava Collections API
Java Collections APIAlex Miller
 
Java Concurrency Idioms
Java Concurrency IdiomsJava Concurrency Idioms
Java Concurrency IdiomsAlex Miller
 

Plus de Alex Miller (20)

Clojure/West Overview (12/1/11)
Clojure/West Overview (12/1/11)Clojure/West Overview (12/1/11)
Clojure/West Overview (12/1/11)
 
Concurrent Stream Processing
Concurrent Stream ProcessingConcurrent Stream Processing
Concurrent Stream Processing
 
Stream Execution with Clojure and Fork/join
Stream Execution with Clojure and Fork/joinStream Execution with Clojure and Fork/join
Stream Execution with Clojure and Fork/join
 
Cracking clojure
Cracking clojureCracking clojure
Cracking clojure
 
Releasing Relational Data to the Semantic Web
Releasing Relational Data to the Semantic WebReleasing Relational Data to the Semantic Web
Releasing Relational Data to the Semantic Web
 
Clojure: The Art of Abstraction
Clojure: The Art of AbstractionClojure: The Art of Abstraction
Clojure: The Art of Abstraction
 
Tree Editing with Zippers
Tree Editing with ZippersTree Editing with Zippers
Tree Editing with Zippers
 
Groovy concurrency
Groovy concurrencyGroovy concurrency
Groovy concurrency
 
Blogging ZOMG
Blogging ZOMGBlogging ZOMG
Blogging ZOMG
 
Innovative Software
Innovative SoftwareInnovative Software
Innovative Software
 
Scaling Your Cache
Scaling Your CacheScaling Your Cache
Scaling Your Cache
 
Caching In The Cloud
Caching In The CloudCaching In The Cloud
Caching In The Cloud
 
Scaling Your Cache And Caching At Scale
Scaling Your Cache And Caching At ScaleScaling Your Cache And Caching At Scale
Scaling Your Cache And Caching At Scale
 
Marshmallow Test
Marshmallow TestMarshmallow Test
Marshmallow Test
 
Strange Loop Conference 2009
Strange Loop Conference 2009Strange Loop Conference 2009
Strange Loop Conference 2009
 
Cold Hard Cache
Cold Hard CacheCold Hard Cache
Cold Hard Cache
 
Scaling Hibernate with Terracotta
Scaling Hibernate with TerracottaScaling Hibernate with Terracotta
Scaling Hibernate with Terracotta
 
Project Fortress
Project FortressProject Fortress
Project Fortress
 
Java Collections API
Java Collections APIJava Collections API
Java Collections API
 
Java Concurrency Idioms
Java Concurrency IdiomsJava Concurrency Idioms
Java Concurrency Idioms
 

Dernier

Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsRoshan Dwivedi
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherRemote DBA Services
 
Top 10 Most Downloaded Games on Play Store in 2024
Top 10 Most Downloaded Games on Play Store in 2024Top 10 Most Downloaded Games on Play Store in 2024
Top 10 Most Downloaded Games on Play Store in 2024SynarionITSolutions
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUK Journal
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingEdi Saputra
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024The Digital Insurer
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdflior mazor
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobeapidays
 
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...Principled Technologies
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfsudhanshuwaghmare1
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)wesley chun
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProduct Anonymous
 

Dernier (20)

Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Top 10 Most Downloaded Games on Play Store in 2024
Top 10 Most Downloaded Games on Play Store in 2024Top 10 Most Downloaded Games on Play Store in 2024
Top 10 Most Downloaded Games on Play Store in 2024
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 

Design Patterns Reconsidered

  • 1. Design Patterns Reconsidered Alex Miller @puredanger
  • 2. 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
  • 3.
  • 4. 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
  • 5. 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
  • 6. 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
  • 7. ...Reconsidered Template Visitor Method Proxy Singleton
  • 9. There can be only one... Singleton - INSTANCE + getInstance() : Singleton - Singleton() + foo() : Object
  • 11. Classic Singleton public final class Singleton {
  • 12. Classic Singleton public final class Singleton { private static Singleton INSTANCE =
  • 13. Classic Singleton public final class Singleton { private static Singleton INSTANCE = new Singleton();
  • 14. Classic Singleton public final class Singleton { private static Singleton INSTANCE = new Singleton(); private Singleton() {}
  • 15. Classic Singleton public final class Singleton { private static Singleton INSTANCE = new Singleton(); private Singleton() {} public static Singleton instance() {
  • 16. Classic Singleton public final class Singleton { private static Singleton INSTANCE = new Singleton(); private Singleton() {} public static Singleton instance() { return INSTANCE;
  • 17. Classic Singleton public final class Singleton { private static Singleton INSTANCE = new Singleton(); private Singleton() {} public static Singleton instance() { return INSTANCE; }
  • 18. Classic Singleton public final class Singleton { private static Singleton INSTANCE = new Singleton(); private Singleton() {} public static Singleton instance() { return INSTANCE; } public Object read() {
  • 19. Classic Singleton public final class Singleton { private static Singleton INSTANCE = new Singleton(); private Singleton() {} public static Singleton instance() { return INSTANCE; } public Object read() { // nasty database call
  • 20. Classic Singleton public final class Singleton { private static Singleton INSTANCE = new Singleton(); private Singleton() {} public static Singleton instance() { return INSTANCE; } public Object read() { // nasty database call }
  • 21. Classic Singleton public final class Singleton { private static Singleton INSTANCE = new Singleton(); private Singleton() {} public static Singleton instance() { return INSTANCE; } public Object read() { // nasty database call } }
  • 22. Things go horribly wrong public class Victim { public void something() { Object foo = Singleton.instance().read(); // etc... } }
  • 23. Things go horribly wrong 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? } }
  • 24. Create Hidden Singletons Coupling!
  • 25. Interfaces to the rescue public interface Singleton { Object read(); } public class SingletonImpl implements Singleton { public Object read() { // nasty database call return null; } }
  • 26. Dependency injection, you’re my hero! public class Victim { private final Singleton singleton; public Victim(Singleton singleton) { this.singleton = singleton; } public void something() { Object foo = singleton.read(); // etc... } }
  • 27. Now we can test public class TestVictim { public void testSomething() { Singleton s = new MockSingleton(); Victim victim = new Victim(s); victim.something(); // assertions } }
  • 28. Push construction up public class Component { private final Victim victim; public Component() { victim = new Victim( new SingletonImpl() ); } }
  • 29. Up Bubble Singletons
  • 31. 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
  • 32. ...Reconsidered Template Visitor Method Proxy Singleton
  • 34. Template Method public void algorithm() { TemplateAlgorithm step1(); + algorithm() step2(); # step1() step3(); # step2() } # step3() ConcreteAlgorithm1 ConcreteAlgorithm2 # step1() # step2() # step2() # step3()
  • 35. Spring MVC Controllers Controller (interface) AbstractController AbstractUrlViewController UrlFilenameViewController BaseCommandController AbstractCommandController AbstractFormController AbstractWizardFormController SimpleFormController CancellableFormController MultiActionController ParameterizableViewController
  • 36.
  • 37. “What we’ve got here is a failure to communicate....”
  • 38. Refactoring to steps Step1Strategy + step1() TemplateAlgorithm - Step1Strategy Step2Strategy - Step2Strategy + step2() - Step3Strategy + algorithm() Step3Strategy + step3() public void algorithm() { step1Strategy.step1(); step2Strategy.step2(); step3Strategy.step3(); }
  • 39. Sharing context Step1Strategy + step1(Context ctx) TemplateAlgorithm - Step1Strategy Step2Strategy - Step2Strategy + step2(Context ctx) - Step3Strategy + algorithm() Step3Strategy + step3(Context ctx) public void algorithm() { Context Context context = new Context(); step1Strategy.step1(context); step2Strategy.step2(context); step3Strategy.step3(context); }
  • 40. 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
  • 41. ...Reconsidered Template Visitor Method Proxy Singleton
  • 42. Composite hierarchy Node operation1() operation2() ConcreteNode1 CompositeNode operation1() operation1() operation2() operation2()
  • 43. Visitor Pattern Node accept(NodeVisitor v) ConcreteNode1 CompositeNode accept(NodeVisitor v) accept(NodeVisitor v) NodeVisitor visit(ConcreteNode1 n) visit(ConcreteNode2 n) ... ConcreteVisitor1 ConcreteVisitor2 visit(ConcreteNode1 n) visit(ConcreteNode1 n) visit(ConcreteNode2 n) visit(ConcreteNode2 n) ... ...
  • 44. N av iga tio n
  • 45. Internal Navigation public class CompositeNode implements Visitable { private List<Node> nodes; public void accept(NodeVisitor v) { v.visit(this); for(Node n : nodes) { v.visit(n); } } }
  • 46. Navigation oracle 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); } } }
  • 47. Navigation Visitor NodeVisitor visit(ConcreteNode1 n) visit(ConcreteNode2 n) ... ConcreteVisitor1 ConcreteVisitor2 visit(ConcreteNode1 n) visit(ConcreteNode1 n) visit(ConcreteNode2 n) visit(ConcreteNode2 n) ... ... NavigationVisitor NavigationVisitor(NodeVisitor v) visit(ConcreteNode1 n) visit(ConcreteNode2 n) ...
  • 48. Evo lutio n
  • 49. Node accept(NodeVisitor v) ConcreteNode1 CompositeNode accept(NodeVisitor v) accept(NodeVisitor v) NewNode accept(NodeVisitor v) NodeVisitor visit(ConcreteNode1 n) visit(ConcreteNode2 n) visit(NewNode n) ... ConcreteVisitor1 ConcreteVisitor2 visit(ConcreteNode1 n) visit(ConcreteNode1 n) visit(ConcreteNode2 n) visit(ConcreteNode2 n) visit(NewNode n) visit(NewNode n) ... ...
  • 50. NodeVisitor visit(ConcreteNode1 n) visit(ConcreteNode2 n) visit(NewNode n) ... BaseVisitor visit(ConcreteNode1 n) visit(ConcreteNode2 n) visit(NewNode n) ... ConcreteVisitor1 ConcreteVisitor2 visit(ConcreteNode1 n) visit(ConcreteNode1 n) visit(ConcreteNode2 n) visit(ConcreteNode2 n) visit(NewNode n) visit(NewNode n) ... ...
  • 51. 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
  • 52. Visitor abort 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;
  • 53. Exceptions public class ComputeVisitor implements ConcreteVisitor { public void visit(ConcreteNode1 n) { try { // blah blah } catch(BadException e) { // what now? } } }
  • 54. What have we learned? • Expression problem is tough • Abstract base classes help plan for evolution • Generics add precision and flexibility by revealing hidden coupling
  • 55. Questions? http://tech.puredanger.com/ presentations/design- patterns-reconsidered