Slide 1

Slide 1 text

A Missing Part of OOP @kentaro

Slide 2

Slide 2 text

@kentaro Software engineer Rubyist / Perl Monger Kentaro Kuribayashi Spiritual Software http://spiritualsoftware.org/

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

https://speakerdeck.com/kentaro/software-and-spiritual-ability

Slide 6

Slide 6 text

Paradigm

Slide 7

Slide 7 text

• Goto + Condition • Structural Programming • Subroutines • Object-Oriented Programming

Slide 8

Slide 8 text

http://www.software-architect.co.uk/slides/sa10-JimCoplien_Patterns.pdf

Slide 9

Slide 9 text

DCI

Slide 10

Slide 10 text

http://qconlondon.com/dl/qcon-london-2010/slides/JimO.Coplien_TheDCIArchitectureLeanAndAgileAtTheCodeLevel.pdf “goto” Programming

Slide 11

Slide 11 text

• Static Class-based OOP is like “goto” programming • It can’t describe use cases as code.

Slide 12

Slide 12 text

“In the old days of FORTRAN and Pascal, I could convert a Use Case scenario into code, give it to my office mate with the scenario description, and ask him or her to desk check it. Today, after the polymorphism and object orientation of 1967, I can't do that. Our ability to reason about systems has been lost.” http://qconlondon.com/dl/qcon-london-2010/slides/JimO.Coplien_TheDCIArchitectureLeanAndAgileAtTheCodeLevel.pdf

Slide 13

Slide 13 text

http://qconlondon.com/dl/qcon-london-2010/slides/JimO.Coplien_TheDCIArchitectureLeanAndAgileAtTheCodeLevel.pdf

Slide 14

Slide 14 text

class MoneyTransfer def initialize(source, destination) @source = source @source.extend(Transferrer) @destination = destination end def execute(amount) @source.transfer_to(@destination, amount) end module Transferrer def transfer_to(destination, amount) self.balance -= amount destination.balance += amount end end end Methodful Role

Slide 15

Slide 15 text

• Interaction of objects happens in a certain context • Methodful role holds methods to be added • Role is combined to object dynamically at runtime

Slide 16

Slide 16 text

Problem

Slide 17

Slide 17 text

http://qconlondon.com/dl/qcon-london-2010/slides/JimO.Coplien_TheDCIArchitectureLeanAndAgileAtTheCodeLevel.pdf

Slide 18

Slide 18 text

We can’t avoid commonalizing even with DCI

Slide 19

Slide 19 text

class FooTransfer def initialize(source, destination) @source = source.extend(Transferrer) @destination = destination end ... class BarTransfer def initialize(source, destination) @source = source.extend(Transferrer) @destination = destination end ... class BazTransfer def initialize(source, destination) @source = source.extend(Transferrer) @destination = destination end ... module Transferrer ... end

Slide 20

Slide 20 text

That’s nothing but “goto”-like programming...

Slide 21

Slide 21 text

• Methods in roles can be called from anywhere. • When we read the code, it’s such a bad dream of “goto”- like programming, isn’t it?

Slide 22

Slide 22 text

What actually matters is commonalization (without any limitation)

Slide 23

Slide 23 text

Solution ( I hope it can be)

Slide 24

Slide 24 text

No content

Slide 25

Slide 25 text

Method-based Limitation

Slide 26

Slide 26 text

module Repository include MethodRepository insert :method1, in: %w[Foo Bar] do; end insert :method2, in: %w[Baz] do; end end class Foo; end class Bar; end class Baz; end class Qux; end

Slide 27

Slide 27 text

Foo.extend(Repository) Bar.extend(Repository) Baz.extend(Repository) Qux.extend(Repository) Foo.respond_to?(:method1) #=> true Bar.respond_to?(:method1) #=> true Baz.respond_to?(:method1) #=> false Qux.respond_to?(:method1) #=> false Foo.respond_to?(:method2) #=> false Bar.respond_to?(:method2) #=> false Baz.respond_to?(:method2) #=> true Qux.respond_to?(:method2) #=> false

Slide 28

Slide 28 text

foo = Foo.new; foo.extend(Repository) bar = Bar.new; bar.extend(Repository) baz = Baz.new; bar.extend(Repository) qux = Qux.new; qux.extend(Repository) foo.respond_to?(:method1) #=> true bar.respond_to?(:method1) #=> true baz.respond_to?(:method1) #=> false qux.respond_to?(:method1) #=> false foo.respond_to?(:method2) #=> false bar.respond_to?(:method2) #=> false baz.respond_to?(:method2) #=> true qux.respond_to?(:method2) #=> false

Slide 29

Slide 29 text

Foo.send(:include, Repository) Bar.send(:include, Repository) Baz.send(:include, Repository) Qux.send(:include, Repository) Foo.new.respond_to?(:method1) #=> true Bar.new.respond_to?(:method1) #=> true Baz.new.respond_to?(:method1) #=> false Qux.new.respond_to?(:method1) #=> false Foo.new.respond_to?(:method2) #=> false Bar.new.respond_to?(:method2) #=> false Baz.new.respond_to?(:method2) #=> true Qux.new.respond_to?(:method2) #=> false

Slide 30

Slide 30 text

Extension/Inclusion-based Limitation

Slide 31

Slide 31 text

module Extendable include MethodRepository extendable_by 'Hoge' end module Includable include MethodRepository includable_by 'Hoge' end class Hoge; end class Fuga; end

Slide 32

Slide 32 text

Hoge.extend(Extendable) Hoge.send(:include, Includable) Fuga.extend(Extendable) Fuga.send(:include, Includable) Extendable/Includable NotPermittedError Raised

Slide 33

Slide 33 text

class FooTransfer def initialize(source, destination) @source = source.extend(Transferrer) @destination = destination end ... class BarTransfer def initialize(source, destination) @source = source.extend(Transferrer) @destination = destination end ... class BazTransfer def initialize(source, destination) @source = source.extend(Transferrer) @destination = destination end ... module Transferrer extendable_by ‘Account’ ... end × Limits extending when class doesn’t comply with definition of the module.

Slide 34

Slide 34 text

• Commonalizes methods in a usual way • But limits them where to be inserted • Methods won’t be called from somewhere we don’t know. So, we won’t be burdened to dig around the code.

Slide 35

Slide 35 text

Recap

Slide 36

Slide 36 text

• DCI is worth considering • We need commonalization even with DCI • Commonalization can cause “goto”-like programming without any limitation • method_repository can help you.