Patterns, patterns everywhere

Patterns, patterns everywhere

Afa6e65b91b46f3317c3d3e94e9255f2?s=128

Grzegorz Witek

October 03, 2014
Tweet

Transcript

  1. PAT T E R N S , PAT T E

    R N S E V E RY W H E R E @ A R N VA L D , A R R R R C A M P 2 0 1 4
  2. D E S I G N PAT T E R

    N ? W H AT I S A
  3. 2 0 Y E A R S L AT E

    R • are GoF design patterns still used today? • are they useful in dynamic languages? • is it worth to learn them? • is it worth to read GoF book?
  4. “ G A N G O F F O U

    R ” PAT T E R N S adapter chain of responsibility visitor mediator proxy flyweight command singleton builder bridge abstract factory factory method template method prototype observer composite strategy decorator facade iterator memento interpreter state
  5. PAT T E R N S T R U C

    T U R E • description (intent, applicability etc.) • implementation (example code, class diagram etc.)
  6. C O M M A N D Encapsulate a request

    as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.
  7. C O M M A N D - U S

    E C A S E • I’m writing a text editor • I want to implement “copy” and “paste” buttons
  8. C O M M A N D - C O

    D E class Button def initialize(command); @command = command; end def on_click; @command.call; end end class Copy def call; clipboard.text = @page.marked_text; end end class Paste def call @page.text[@cursor.position] += @clipboard.text end end copy_button = Button.new(Copy.new) paste_button = Button.new(Paste.new)
  9. C O M M A N D - C O

    D E class Button def initialize(&blk); @command = blk; end def on_click; @command.call; end end copy_button = Button.new do clipboard.text = @page.marked_text end paste_button = Button.new do page.text[cursor.position] += clipboard.text end
  10. C O M M A N D Encapsulate a request

    as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.
  11. C O M M A N D - VA R

    I A N T S class Paste def call @start_position = cursor.position @text = clipboard page.text[@start_position] += @text end def undo text.slice!(@start_position, @text.length) end end
  12. C O M M A N D • workaround for

    language missing feature • still useful in some cases
  13. D E C O R AT O R Attach additional

    responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.
  14. D E C O R AT O R - U

    S E C A S E • I’m writing a text editor • I want to implement preview in html format
  15. class Text def render; @body; end end class TextDecorator def

    initialize(text); @text = text; end def render; @text.render; end end class ItalicTextDecorator < TextDecorator def render; "<i>#{super}</i>"; end end D E C O R AT O R - C O D E
  16. text = Text.new("this is text") decoratedText = BoldTextDecorator.new( ItalicTextDecorator.new(text) )

    decoratedText.render # => <b><i>this is text</i></b> D E C O R AT O R - C O D E
  17. D E C O R AT O R - A

    LT E R N AT I V E module ItalicTextDecorator def render; "<i>#{super}</i>"; end end module BoldTextDecorator def render; "<b>#{super}</b>"; end end text = Text.new("this is text") text.extend(ItalicTextDecorator) text.extend(BoldTextDecorator) text.render # => <b><i>this is text</i></b>
  18. D E C O R AT O R • workaround

    for missing feature (extending objects during runtime) • name still used, despite going beyond traditional definition
  19. I T E R AT O R Provide a way

    to access the elements of an aggregate object sequentially without exposing its underlying representation.
  20. I T E R AT O R - U S

    E C A S E • I’m writing a text editor • I want to implement opening multiple files • for each file a new window should open that will print text on the screen
  21. def open_files(paths) paths.each { |path| open_file(path) } end def open_file(path)

    Window.new do |window| file = File.open(path) while !file.eof? window.text << file.readline end end end I T E R AT O R - C O D E
  22. I T E R AT O R • made it

    to cores or standard libraries of many languages
  23. S I N G L E T O N Ensure

    a class only has one instance, and provide a global point of access to it.
  24. S I N G L E T O N -

    U S E C A S E • I’m writing a text editor • I want to implement settings • I want to be sure there’s just one place settings are stored
  25. class Settings class << self private :new def instance @instance

    ||= new end end end S I N G L E T O N - C O D E
  26. require 'singleton' class Settings include Singleton end Settings.new # =>

    raises an error Settings.instance # <Settings:0x007fcea4142bf0> Settings.instance # <Settings:0x007fcea4142bf0> Settings.instance # <Settings:0x007fcea4142bf0> S I N G L E T O N - C O D E
  27. Settings.instance # <Settings:0x007fcea4142bf0> Settings.send(:new) #<Settings:0x007f8613116890> S I N G L

    E T O N - C O D E
  28. Settings = Object # some warnings here Settings.new #<Object:0x007f86138d8740> S

    I N G L E T O N - C O D E
  29. require 'ostruct' $settings = OpenStruct.new S I N G L

    E T O N - C O D E
  30. S I N G L E T O N •

    available in standard library • considered anti-pattern • Ruby’s features make it very similar to any global variable
  31. O B S E R V E R Define a

    one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
  32. O B S E R V E R - U

    S E C A S E • I’m writing a text editor • I want to implement styles • All pieces of text having specific style should change when this style changes
  33. class Style def update(attrs) attrs.each { |k,v| send(:"#{k}=", v) }

    notify_observers end def notify_observers @observers.each { |o| o.notify(self) } end def add_observer(observer) @observers << observer end end O B S E R V E R - C O D E
  34. class Paragraph def apply_style(style) style.add_observer(self) end def notify(style) update_formatting(style) end

    end O B S E R V E R - C O D E
  35. class Style include Observable def update(attrs) attrs.each { |k,v| send(:"#{k}=",

    v) } changed notify_observers end end O B S E R V E R - C O D E
  36. O B S E R V E R • available

    in standard library • sometimes considered anti-pattern (coupling) • publisher-subscriber preferred
  37. T E M P L AT E M E T

    H O D Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure.
  38. T E M P L AT E M E T

    H O D • used very commonly • nobody uses this name
  39. A D A P T E R Convert the interface

    of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.
  40. A D A P T E R • used very

    commonly • well-known name
  41. B R I D G E Decouple an abstraction from

    its implementation so that the two can vary independently.
  42. B R I D G E • used commonly •

    nobody uses this name
  43. FA C A D E Provide a unified interface to

    a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.
  44. FA C A D E • used very commonly •

    nobody uses this name
  45. D E S I G N PAT T E R

    N S ? W H Y D O N ’ T W E L I K E
  46. C O N T R O V E R S

    Y • solutions to non-existent problems • remind of static languages • overused
  47. D E S I G N PAT T E R

    N S 2 0 Y E A R S L AT E R • considered harmful (Singleton, Observer) • useless in languages with certain features (Abstract Factory) • deprecated (Observer) • useful in rare cases (Command, Builder)
  48. D E S I G N PAT T E R

    N S 2 0 Y E A R S L AT E R • core features (Iterator) • standard library (Observer, Singleton) • commonly used (Adaptor, Decorator) • used for communication purpose (Iterator, Decorator, Observer)
  49. M O R E PAT T E R N S

    W E N E E D
  50. ( N O T S O ) N E W

    PAT T E R N S • null object • dependency injection • extension object • type object
  51. M I S S I N G PAT T E

    R N S ( P R A C T I C E S ? ) • meta-programming • DSLs
  52. R E S O U R C E S •

    R. Olsen “Design Patterns in Ruby” • E. Gamma et al. “Design Patterns: Elements of Reusable Object-Oriented Software” • C. Haynes “Design Patterns and the Proper Cultivation Thereof” (talk) • http://c2.com/cgi/wiki
  53. PAT T E R N S , PAT T E

    R N S E V E RY W H E R E @ A R N VA L D , A R R R R C A M P 2 0 1 4