Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

D E S I G N PAT T E R N ? W H AT I S A

Slide 3

Slide 3 text

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?

Slide 4

Slide 4 text

“ 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

Slide 5

Slide 5 text

PAT T E R N S T R U C T U R E • description (intent, applicability etc.) • implementation (example code, class diagram etc.)

Slide 6

Slide 6 text

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.

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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)

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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.

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

C O M M A N D • workaround for language missing feature • still useful in some cases

Slide 13

Slide 13 text

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.

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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; "#{super}"; end end D E C O R AT O R - C O D E

Slide 16

Slide 16 text

text = Text.new("this is text") decoratedText = BoldTextDecorator.new( ItalicTextDecorator.new(text) ) decoratedText.render # => this is text D E C O R AT O R - C O D E

Slide 17

Slide 17 text

D E C O R AT O R - A LT E R N AT I V E module ItalicTextDecorator def render; "#{super}"; end end module BoldTextDecorator def render; "#{super}"; end end text = Text.new("this is text") text.extend(ItalicTextDecorator) text.extend(BoldTextDecorator) text.render # => this is text

Slide 18

Slide 18 text

D E C O R AT O R • workaround for missing feature (extending objects during runtime) • name still used, despite going beyond traditional definition

Slide 19

Slide 19 text

I T E R AT O R Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

I T E R AT O R • made it to cores or standard libraries of many languages

Slide 23

Slide 23 text

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.

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

Settings.instance # Settings.send(:new) # S I N G L E T O N - C O D E

Slide 28

Slide 28 text

Settings = Object # some warnings here Settings.new # S I N G L E T O N - C O D E

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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.

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

O B S E R V E R • available in standard library • sometimes considered anti-pattern (coupling) • publisher-subscriber preferred

Slide 37

Slide 37 text

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.

Slide 38

Slide 38 text

T E M P L AT E M E T H O D • used very commonly • nobody uses this name

Slide 39

Slide 39 text

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.

Slide 40

Slide 40 text

A D A P T E R • used very commonly • well-known name

Slide 41

Slide 41 text

B R I D G E Decouple an abstraction from its implementation so that the two can vary independently.

Slide 42

Slide 42 text

B R I D G E • used commonly • nobody uses this name

Slide 43

Slide 43 text

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.

Slide 44

Slide 44 text

FA C A D E • used very commonly • nobody uses this name

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

C O N T R O V E R S Y • solutions to non-existent problems • remind of static languages • overused

Slide 47

Slide 47 text

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)

Slide 48

Slide 48 text

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)

Slide 49

Slide 49 text

M O R E PAT T E R N S W E N E E D

Slide 50

Slide 50 text

( N O T S O ) N E W PAT T E R N S • null object • dependency injection • extension object • type object

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

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