125
Classes Objects: 那些 OOP 教我的事 http://ihower.tw 2013/10/26@ RubyConf China

從 Classes 到 Objects: 那些 OOP 教我的事

  • View
    5.428

  • Download
    1

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: 從 Classes 到 Objects: 那些 OOP 教我的事

從 Classes 到 Objects:那些 OOP 教我的事

http://ihower.tw2013/10/26@ RubyConf China

Page 2: 從 Classes 到 Objects: 那些 OOP 教我的事

我是誰• 張⽂文鈿 a.k.a. ihower

• http://ihower.tw

• 來⾃自台灣

Page 3: 從 Classes 到 Objects: 那些 OOP 教我的事
Page 4: 從 Classes 到 Objects: 那些 OOP 教我的事
Page 5: 從 Classes 到 Objects: 那些 OOP 教我的事

Ruby Taiwanhttp://ruby.tw

Page 6: 從 Classes 到 Objects: 那些 OOP 教我的事

RubyConf Taiwan2013/4/25-26

Page 7: 從 Classes 到 Objects: 那些 OOP 教我的事

Agenda

• OOP

• class-oriented

• object-oriented

• Role-oriented

• Context-oriented

• DCI

• Conclusion

Page 8: 從 Classes 到 Objects: 那些 OOP 教我的事

Object = Identity + Behavior + State

Page 9: 從 Classes 到 Objects: 那些 OOP 教我的事

Identitya = "foo"b = "foo"

a.object_id # 70178176631620b.object_id # 70178176659140

a == b # truea.equal?(b) # false

Page 10: 從 Classes 到 Objects: 那些 OOP 教我的事

Behavior"foo".methods => [:<=>, :==, :===, :eql?, :hash, :casecmp, :+, :*, :%, :[], :[]=, :insert, :length, :size, :bytesize, :empty?, :=~, :match, :succ, :succ!, :next, :next!, :upto, :index, :rindex, :replace, :clear, :chr, :getbyte, :setbyte, :byteslice, :to_i, :to_f, :to_s, :to_str, :inspect, :dump, :upcase, :downcase, :capitalize, :swapcase, :upcase!, :downcase!, :capitalize!, :swapcase!, :hex, :oct, :split, :lines, :bytes, :chars, :codepoints, :reverse, :reverse!, :concat, :<<, :prepend, :crypt, :intern, :to_sym, :ord, :include?, :start_with?, :end_with?, :scan, :ljust, :rjust, :center, :sub, :gsub, :chop, :chomp, :strip, :lstrip, :rstrip, :sub!, :gsub!, :chop!, :chomp!, :strip!, :lstrip!, :rstrip!, :tr, :tr_s, :delete, :squeeze, :count, :tr!, :tr_s!, :delete!, :squeeze!, :each_line, :each_byte, :each_char, :each_codepoint, :sum, :slice, :slice!, :partition, :rpartition, :encoding, :force_encoding, :valid_encoding?, :ascii_only?, :unpack, :encode, :encode!, :to_r, :to_c, :>, :>=, :<, :<=, :between?, :nil?, :!~, :class, :singleton_class, :clone, :dup, :initialize_dup, :initialize_clone, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :freeze, :frozen?, :methods, :singleton_methods, :protected_methods, :private_methods, :public_methods, :instance_variables, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :instance_of?, :kind_of?, :is_a?, :tap, :send, :public_send, :respond_to?, :respond_to_missing?, :extend, :display, :method, :public_method, :define_singleton_method, :object_id, :to_enum, :enum_for, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__, :__id__]

Page 11: 從 Classes 到 Objects: 那些 OOP 教我的事

Stateclass Person def name @name end def name=(name) @name = name end end

a = Person.newb = Person.new

a.name = "Foo"b.name = "Bar"

Page 12: 從 Classes 到 Objects: 那些 OOP 教我的事

State (cont.)

a = Person.newb = Person.new

a.name = "Foo"b.name = "Bar"

Page 13: 從 Classes 到 Objects: 那些 OOP 教我的事

class Person attr_accessor :name end

Page 14: 從 Classes 到 Objects: 那些 OOP 教我的事

封裝 Encapsulation

• 物件的 State 狀態被封裝起來

• 必須透過外在的 Behavior,也就是 Method ⽅方法來存取操作

Page 15: 從 Classes 到 Objects: 那些 OOP 教我的事

多型 Polymorphism

• Duck-typing in Ruby

• 不管物件的類型,只要有相同的介⾯面,就可以呼叫使⽤用

Page 16: 從 Classes 到 Objects: 那些 OOP 教我的事

class Org attr_accessor :nameend

[Person.new, Org.new].each do |p| puts p.nameend

Page 17: 從 Classes 到 Objects: 那些 OOP 教我的事

OOP = objects + messages

Page 18: 從 Classes 到 Objects: 那些 OOP 教我的事

Sending Message 就是呼叫物件的⽅方法

內部狀態@name

呼叫 name ⽅方法

person

Page 19: 從 Classes 到 Objects: 那些 OOP 教我的事

runtime picture

objobj

obj

obj

obj

obj

obj

obj

Page 20: 從 Classes 到 Objects: 那些 OOP 教我的事

class-oriented design?

Page 21: 從 Classes 到 Objects: 那些 OOP 教我的事

class-based OOP

Page 22: 從 Classes 到 Objects: 那些 OOP 教我的事

class-based OOP

• 物件需要⼀一種⽅方式可以⽅方便⽣生成

Page 23: 從 Classes 到 Objects: 那些 OOP 教我的事

class-based OOP

• 物件需要⼀一種⽅方式可以⽅方便⽣生成• 絕⼤大部分的 OO 程式語⾔言都⽀支援 class-based

Page 24: 從 Classes 到 Objects: 那些 OOP 教我的事

class-based OOP

• 物件需要⼀一種⽅方式可以⽅方便⽣生成• 絕⼤大部分的 OO 程式語⾔言都⽀支援 class-based

• 是 Object 的 template 樣板

Page 25: 從 Classes 到 Objects: 那些 OOP 教我的事

class-based OOP

• 物件需要⼀一種⽅方式可以⽅方便⽣生成• 絕⼤大部分的 OO 程式語⾔言都⽀支援 class-based

• 是 Object 的 template 樣板

• 是 Object 的 factory ⼯工廠

Page 26: 從 Classes 到 Objects: 那些 OOP 教我的事

class-oriented?

Page 27: 從 Classes 到 Objects: 那些 OOP 教我的事

class-oriented?

• 使⽤用 class 概念來設計整個系統

Page 28: 從 Classes 到 Objects: 那些 OOP 教我的事

class-oriented?

• 使⽤用 class 概念來設計整個系統

• 找出系統的 nouns,以資料為中⼼心,將物件⽤用類別進⾏行分類 (Data-centric)

Page 29: 從 Classes 到 Objects: 那些 OOP 教我的事

class-oriented?

• 使⽤用 class 概念來設計整個系統

• 找出系統的 nouns,以資料為中⼼心,將物件⽤用類別進⾏行分類 (Data-centric)

• 愛⽤用繼承架構

Page 30: 從 Classes 到 Objects: 那些 OOP 教我的事

class-oriented?

• 使⽤用 class 概念來設計整個系統

• 找出系統的 nouns,以資料為中⼼心,將物件⽤用類別進⾏行分類 (Data-centric)

• 愛⽤用繼承架構• 最後得到系統的 static representation

Page 31: 從 Classes 到 Objects: 那些 OOP 教我的事

A static class diagram

Page 32: 從 Classes 到 Objects: 那些 OOP 教我的事

Data-centric

• 例如,⼀一個 e-commerce 系統:

• Product

• Invoice

• User

• 將需要的⽅方法定義在每個類別上

Page 33: 從 Classes 到 Objects: 那些 OOP 教我的事

A Product model

class Product validates_presence_of :name end

Page 34: 從 Classes 到 Objects: 那些 OOP 教我的事

不斷加⽅方法進來class Product validates_presence_of :name

def add_to_billing(billing) billing.items << self end end

Page 35: 從 Classes 到 Objects: 那些 OOP 教我的事

A fat Product modelclass Product validates_presence_of :name, :price

def add_to_billing(order) order.items << self end def tag(name) #... end

def self.export #... end def sales_report #... end end

Page 36: 從 Classes 到 Objects: 那些 OOP 教我的事

你以為很多物件在互動

objobj

obj

obj

obj

obj

obj

obj

Page 37: 從 Classes 到 Objects: 那些 OOP 教我的事

其實只有少數幾種物件

User Product

Invoice

Page 38: 從 Classes 到 Objects: 那些 OOP 教我的事

class Product def A def B def C ... ... ... ... ...end

class Invoice def X def Y def Z ... ... ... ... ...end

class User def Q def W def E ... ... ... ... ...end

三種類型的物件

Page 39: 從 Classes 到 Objects: 那些 OOP 教我的事

最後變成萬能的 God Object!

Page 40: 從 Classes 到 Objects: 那些 OOP 教我的事

What’s moreObject-oriented?

如何能更善⽤用 Object?

Page 41: 從 Classes 到 Objects: 那些 OOP 教我的事

是什麼 v.s. 做什麼

Page 42: 從 Classes 到 Objects: 那些 OOP 教我的事

是什麼 v.s. 做什麼

• ⼀一個物件”是什麼” (Being) 跟作什麼 (Doing) 是分開的概念

Page 43: 從 Classes 到 Objects: 那些 OOP 教我的事

是什麼 v.s. 做什麼

• ⼀一個物件”是什麼” (Being) 跟作什麼 (Doing) 是分開的概念

• ⼀一個物件需要有什麼⽅方法,跟當時的⾓角⾊色和情境有關係

Page 44: 從 Classes 到 Objects: 那些 OOP 教我的事

是什麼 v.s. 做什麼

• ⼀一個物件”是什麼” (Being) 跟作什麼 (Doing) 是分開的概念

• ⼀一個物件需要有什麼⽅方法,跟當時的⾓角⾊色和情境有關係

• Responsibility-centric 以職責為中⼼心,將物件進⾏行分類

Page 45: 從 Classes 到 Objects: 那些 OOP 教我的事

1. 根據 Roles 來區分物件可以做什麼

Page 46: 從 Classes 到 Objects: 那些 OOP 教我的事

def work end

def rest end def approve end def review end

Page 47: 從 Classes 到 Objects: 那些 OOP 教我的事

def work end

def rest end def approve end def review end

Roles:Employee

person

Page 48: 從 Classes 到 Objects: 那些 OOP 教我的事

def work end

def rest end def approve end def review end

Roles:Manager

person

Page 49: 從 Classes 到 Objects: 那些 OOP 教我的事

Role-oriented

• 不同⾓角⾊色有不同責任,需要的⽅方法也就不同

• ⽤用單⼀一繼承⾏行不通的,⼀一個物件可能同時有好幾個⾓角⾊色

Page 50: 從 Classes 到 Objects: 那些 OOP 教我的事

def buy end

def complain end def approve end def review end

Role:Manager

Role:Customer

Page 51: 從 Classes 到 Objects: 那些 OOP 教我的事

def buy end

def complain end def approve end def review end

Role:Manager

Role:Customer

Roles:CustomerManager

person

Page 52: 從 Classes 到 Objects: 那些 OOP 教我的事

怎麼實作?We represent roles as identifiers ... they [roles] may just be pointers to role-bound object, or macros, or

function or something else.

- Lean Architecture p.240

Page 53: 從 Classes 到 Objects: 那些 OOP 教我的事

⽅方法⼀一: Composition

Page 54: 從 Classes 到 Objects: 那些 OOP 教我的事

Object Composition

Page 55: 從 Classes 到 Objects: 那些 OOP 教我的事

Object Composition

• ⼀一個物件裡包其他物件

Page 56: 從 Classes 到 Objects: 那些 OOP 教我的事

Object Composition

• ⼀一個物件裡包其他物件• 靜態程式語⾔言的唯⼀一選擇

Page 57: 從 Classes 到 Objects: 那些 OOP 教我的事

Object Composition

• ⼀一個物件裡包其他物件• 靜態程式語⾔言的唯⼀一選擇• 眾多 Design Pattern

Page 58: 從 Classes 到 Objects: 那些 OOP 教我的事

class Person

def initialize(role) @role_behavior = role end def say @role_behavior.say end end

Page 59: 從 Classes 到 Objects: 那些 OOP 教我的事

class EmployeeRole def say puts "done!" endend

class ManagerRole def say puts "solid!" endend

Page 60: 從 Classes 到 Objects: 那些 OOP 教我的事

Strategy Pattern!

p1 = Person.new(ManagerRole.new) p2 = Person.new(EmployeeRole.new)

Page 61: 從 Classes 到 Objects: 那些 OOP 教我的事

person

employeerole

person

managerrole

Page 62: 從 Classes 到 Objects: 那些 OOP 教我的事

或是換個組合⽅方向?

Page 63: 從 Classes 到 Objects: 那些 OOP 教我的事

require 'delegate'class Personend

class EmployeeRole < SimpleDelegator def say puts "done!" endend

class ManagerRole < SimpleDelegator def fly puts "solid!" endend

Page 64: 從 Classes 到 Objects: 那些 OOP 教我的事

require 'delegate'class Personend

class EmployeeRole < SimpleDelegator def say puts "done!" endend

class ManagerRole < SimpleDelegator def fly puts "solid!" endend

Page 65: 從 Classes 到 Objects: 那些 OOP 教我的事

p1 = EmployeeRole.new(Person.new)p2 = ManagerRole.new(Person.new)

Decorator Pattern

Page 66: 從 Classes 到 Objects: 那些 OOP 教我的事

employee

person

manager

person

Page 67: 從 Classes 到 Objects: 那些 OOP 教我的事

Strategy v.s. Decorator

Page 68: 從 Classes 到 Objects: 那些 OOP 教我的事

Strategy v.s. Decorator

• Strategy Pattern

• 相同⽅方法,但是不同⾓角⾊色有不同演算法時

Page 69: 從 Classes 到 Objects: 那些 OOP 教我的事

Strategy v.s. Decorator

• Strategy Pattern

• 相同⽅方法,但是不同⾓角⾊色有不同演算法時

• Decorator Pattern

• 當你想新增物件的⾓角⾊色⾏行為時

Page 70: 從 Classes 到 Objects: 那些 OOP 教我的事

Object Composition

• Composition 很強⼤大

• 但是也可以搞的很複雜,特別是參數和狀態如何在物件之間流通....

Page 71: 從 Classes 到 Objects: 那些 OOP 教我的事

⽅方法⼆二: Mixin

Page 72: 從 Classes 到 Objects: 那些 OOP 教我的事

A Product modelclass Product validates_presence_of :name def add_to_billing(billing) billing.items << self end

end

Page 73: 從 Classes 到 Objects: 那些 OOP 教我的事

Orderable Role

module Billingable

def add_to_billing(billing) billing.items << self end end

Page 74: 從 Classes 到 Objects: 那些 OOP 教我的事

class Product

validates_presence_of :name include Billingable

end

Page 75: 從 Classes 到 Objects: 那些 OOP 教我的事

class Product validates_presence_of :name include Billingable include Taggable include Exporter include Reporter

end

Page 76: 從 Classes 到 Objects: 那些 OOP 教我的事
Page 77: 從 Classes 到 Objects: 那些 OOP 教我的事

Rails4

• app/models/concerns

• app/controllers/concerns

Page 78: 從 Classes 到 Objects: 那些 OOP 教我的事

批評

• 只是 copy-paste ⽽而已

• module 本質上還是繼承 inheritance,不若 composition 容易替換

Page 79: 從 Classes 到 Objects: 那些 OOP 教我的事

Poor man’s role-oriented design

Simple, Quick and Dirty

Page 80: 從 Classes 到 Objects: 那些 OOP 教我的事

是什麼 v.s. 做什麼

• ⼀一個物件”是什麼” (Being) 跟作什麼 (Doing) 是分開的概念

• ⼀一個物件需要有什麼⽅方法,跟當時的⾓角⾊色和情境有關係

• Responsibility-centric 以職責為中⼼心,將物件進⾏行分類

Page 81: 從 Classes 到 Objects: 那些 OOP 教我的事

2. 根據情境來區分物件可以做什麼

Page 82: 從 Classes 到 Objects: 那些 OOP 教我的事

def buy end

def complain end def approve end def review end

Page 83: 從 Classes 到 Objects: 那些 OOP 教我的事

def buy end

def complain end def approve end def review end

購物情境才需要

Page 84: 從 Classes 到 Objects: 那些 OOP 教我的事

def buy end

def complain end def approve end def review end

客服情境才需要

Page 85: 從 Classes 到 Objects: 那些 OOP 教我的事

Use case

• 不同的 User case 特定情境,物件需要的⽅方法不⼀一樣

• 例如註冊流程、購物流程

Page 86: 從 Classes 到 Objects: 那些 OOP 教我的事

怎麼實作?

Page 87: 從 Classes 到 Objects: 那些 OOP 教我的事

還是 Composition

Page 88: 從 Classes 到 Objects: 那些 OOP 教我的事

⽽而且有很多種 Patterns

• Service object

• Query object

• Form object

• View object

• Policy object

• ....根據情境分類....

Page 89: 從 Classes 到 Objects: 那些 OOP 教我的事

Service Objecta.k.a. Command Pattern 包裝跨 Data Model 的操作

class BillingControllers < ApplicationController before_filter :find_current_billing def add_product @product = Product.find(params[:product_id]) BillingService.new(@billing, @product).perform! end end

Page 90: 從 Classes 到 Objects: 那些 OOP 教我的事

Service Objectclass BillingService

def initialize(billling, product) @billling = billling @product = product end def perform! add_product_to_billling(@billling, @product) end private def add_product_to_billling(billling, product) billling.items << product end end

Page 91: 從 Classes 到 Objects: 那些 OOP 教我的事

Query Object包裝複雜的 SQL 查詢

class ProductQuery def initialize(relation = Product.scoped) @relation = relation end def by_regions(region_ids = nil) if region_ids.present? countrys = RegionCountry.where(:region_id => region_ids).pluck(:country_alpha2) @relation = @relation.where(:country => countrys) end self end end

@products = ProductQuery.new.by_regions(region_ids)

Page 92: 從 Classes 到 Objects: 那些 OOP 教我的事

View Object包裹給 Rails View 使⽤用

class DashboardView

def initialize(company) @company = company end def arr #... end def mrr #... end def cac #... end end

Page 93: 從 Classes 到 Objects: 那些 OOP 教我的事

Form Object搭配 Rails 的表單

class Signup include Virtus

extend ActiveModel::Naming include ActiveModel::Conversion include ActiveModel::Validations

attr_reader :user attr_reader :company

attribute :name, String attribute :company_name, String attribute :email, String

validates :email, presence: true # … more validations …

# Forms are never themselves persisted def persisted? false end

def save if valid? persist! true else false end end

private

def persist! @company = Company.create!(name: company_name) @user = @company.users.create!(name: name, email: email) endend

Page 94: 從 Classes 到 Objects: 那些 OOP 教我的事

class SignupsController < ApplicationController def create @signup = Signup.new(params[:signup])

if @signup.save redirect_to dashboard_path else render "new" end endend

Page 95: 從 Classes 到 Objects: 那些 OOP 教我的事
Page 96: 從 Classes 到 Objects: 那些 OOP 教我的事

增加物件的多樣性避免肥⼤大的類別

objobj

obj

obj

obj

obj

obj

obj

Page 97: 從 Classes 到 Objects: 那些 OOP 教我的事

DCI⾓角⾊色+情境

將 Behavior 跟 Data model 分開的更徹底

Page 98: 從 Classes 到 Objects: 那些 OOP 教我的事

DCI

Page 99: 從 Classes 到 Objects: 那些 OOP 教我的事

DCI

• Data: 資料

Page 100: 從 Classes 到 Objects: 那些 OOP 教我的事

DCI

• Data: 資料

• 例如 Product

Page 101: 從 Classes 到 Objects: 那些 OOP 教我的事

DCI

• Data: 資料

• 例如 Product

• Context: 情境

Page 102: 從 Classes 到 Objects: 那些 OOP 教我的事

DCI

• Data: 資料

• 例如 Product

• Context: 情境

• 例如加⼊入購物⾞車這個 Use case

Page 103: 從 Classes 到 Objects: 那些 OOP 教我的事

DCI

• Data: 資料

• 例如 Product

• Context: 情境

• 例如加⼊入購物⾞車這個 Use case

• Interaction: ⾏行為

Page 104: 從 Classes 到 Objects: 那些 OOP 教我的事

DCI

• Data: 資料

• 例如 Product

• Context: 情境

• 例如加⼊入購物⾞車這個 Use case

• Interaction: ⾏行為

• 例如加⼊入購物⾞車這個⽅方法

Page 105: 從 Classes 到 Objects: 那些 OOP 教我的事

呼叫⽅方式class BillingControllers < ApplicationController before_filter :find_current_billing def add_product @product = Product.find(params[:product_id]) BillingContext.new(@billing, @product).perform! end end

Page 106: 從 Classes 到 Objects: 那些 OOP 教我的事

class BillingContext def initialize(billling, product) @billling = billling end def perform! @product.add_to_billling(@billling) end end

情境

Page 107: 從 Classes 到 Objects: 那些 OOP 教我的事

class Product < ActiveRecord::Base # 注意,這裡不放 Behavior 了end

Page 108: 從 Classes 到 Objects: 那些 OOP 教我的事

class BillingContext module Billlingable def add_to_billling(billling) billling.items << self end end end

Billingable Role

Page 109: 從 Classes 到 Objects: 那些 OOP 教我的事

class BillingContext def initialize(billling, product) @billling = billling @product.extend(Billingable) end def perform! @product.add_to_billling(@billling) end module Billlingable def add_to_billling(billling) billling.items << self end end end

Page 110: 從 Classes 到 Objects: 那些 OOP 教我的事

data model 的 behavior,是 run-time 的時候,根據當時的需要

動態 extend 進去物件

Page 111: 從 Classes 到 Objects: 那些 OOP 教我的事

Productclass

沒有⾏行為

compile-time run-time

Productobject 加上⾏行為

extend ⾏行為模組

Page 112: 從 Classes 到 Objects: 那些 OOP 教我的事

批評

Page 113: 從 Classes 到 Objects: 那些 OOP 教我的事

⽤用 Wrapper ?require 'delegate'class BillingContext def initialize(billling, product) @billling = billling @product = BillingableProduct.new(product) end def perform! @product.add_to_billling(@billling) end class BilllingableProduct < SimpleDelegator def add_to_billling(billling) billling.items << __getobj__ end end end

Page 114: 從 Classes 到 Objects: 那些 OOP 教我的事

self 精神分裂http://en.wikipedia.org/wiki/Schizophrenia_(object-oriented_programming)

• __getobj__

• 多包⼀一層,物件的 identify 和 class 是不⼀一樣的,需要處理資料傳遞和分享的問題

• 就算⾃自⼰己寫 Wrapper,也很⿇麻煩

• 更別提如果有兩個以上的 Roles

Page 115: 從 Classes 到 Objects: 那些 OOP 教我的事

Benchmark並沒有數量級的差距

0

0.1

0.2

0.3

0.4

inherited mixin wrapper simple delegator extend(DCI)

https://gist.github.com/ihower/7160400

Page 116: 從 Classes 到 Objects: 那些 OOP 教我的事

結論Conclusion

Page 117: 從 Classes 到 Objects: 那些 OOP 教我的事

結論

Page 118: 從 Classes 到 Objects: 那些 OOP 教我的事

結論

• 從 Data-Centric 到 Responsibility-centric

Page 119: 從 Classes 到 Objects: 那些 OOP 教我的事

結論

• 從 Data-Centric 到 Responsibility-centric

• 物件的 Behavior 會因為⾓角⾊色和情境⽽而需求不同,可以分開。⽽而不需要通通塞在 data model 上

Page 120: 從 Classes 到 Objects: 那些 OOP 教我的事

結論 (cont.)

Page 121: 從 Classes 到 Objects: 那些 OOP 教我的事

結論 (cont.)

• 在靜態語⾔言中,Composition 是唯⼀一解

Page 122: 從 Classes 到 Objects: 那些 OOP 教我的事

結論 (cont.)

• 在靜態語⾔言中,Composition 是唯⼀一解

• 但是在 Ruby 中,善⽤用⼀一些技巧可以事半功倍

• Mixins

• DCI

Page 123: 從 Classes 到 Objects: 那些 OOP 教我的事

結論 (cont.)

• 在靜態語⾔言中,Composition 是唯⼀一解

• 但是在 Ruby 中,善⽤用⼀一些技巧可以事半功倍

• Mixins

• DCI

• 因為 Ruby 把 class 當作 behavior 的容器,⽽而不是死的 template,所以可以動態地修改⾏行為

Page 124: 從 Classes 到 Objects: 那些 OOP 教我的事

Reference:• Object-Oriented Programming: Objects over Classes (The ThoughtWorks Anthology 2)

• Clean Ruby, Jim Gay

• Rails Developers Should Take DCI Seriously http://gilesbowkett.blogspot.tw/2012/12/rails-developers-should-take-dci.html

• http://mikepackdev.com/blog_posts/24-the-right-way-to-code-dci-in-ruby

• http://dci-in-ruby.info/

• https://practicingruby.com/articles/responsibility-centric-vs-data-centric-design

• http://37signals.com/svn/posts/3372-put-chubby-models-on-a-diet-with-concerns

• http://blog.gemnasium.com/post/60091511603/casting-adding-behavior-to-objects-without-using

• http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/

• https://speakerdeck.com/stefanoverna/fat-models-must-die

Page 125: 從 Classes 到 Objects: 那些 OOP 教我的事

謝謝!歡迎參加明晚 Faria Systems 的

After Party