Slide 1

Slide 1 text

STOP! Use case time! Or, a brief introduction to DCI.

Slide 2

Slide 2 text

Who am I? André Medeiros Rubyist for 7+ years @superdealloc github.com/andremedeiros quintel.com

Slide 3

Slide 3 text

What’s DCI?

Slide 4

Slide 4 text

How I develop apps •UI first approach •UI directly maps to operations within the code •MVC doesn’t always conform to this standard of development

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

DCI is great for this approach Invented by Trygve Reenskaug Comes in where MVC fails: capturing behavior Places interaction in obvious places Models represent entities, not behavior Splits what an object is from what it does

Slide 8

Slide 8 text

D is for Data What the object is Persistence Structure

Slide 9

Slide 9 text

C is for Cookie Context Class which enacts one or more use cases Instantiated by a user action Mixes in participating objects with Roles Responsible for acting out the use case

Slide 10

Slide 10 text

I is for Interaction What the system does Logic is contained in Role modules Implemented by mixing in objects with Roles in a given Context or use case

Slide 11

Slide 11 text

How it works Controller Context starts use case

Slide 12

Slide 12 text

How it works Controller Context starts use case Context Object(s) finds or creates the participating objects

Slide 13

Slide 13 text

How it works Controller Context starts use case Context Object(s) mixes in all the roles needed Role Role Role

Slide 14

Slide 14 text

How it works Controller Context starts use case Context Object(s) invokes the role methods Role Role Role

Slide 15

Slide 15 text

Code Samples

Slide 16

Slide 16 text

# app/controllers/transfers_controller.rb (before DCI) class TransfersController def create @source = Account.find(params[:source_id]) @destination = Account.find(params[:dest_id]) @source.balance -= params[:amount] @destination.balance += params[:amount] end end

Slide 17

Slide 17 text

# app/controllers/transfers_controller.rb (after DCI) class TransfersController def create @source = Account.find(params[:source_id]) @destination = Account.find(params[:dest_id]) mt = MoneyTransfer.new(@source, @destination) mt.execute(params[:amount]) end end

Slide 18

Slide 18 text

# app/contexts/money_transfer.rb class MoneyTransfer def initialize(source, destination) @source = source @destination = destination assign_transferrer(@source) end def execute(amount) @source.transfer_to(@destination, amount) end private def assign_transferrer(account) account.extend(Transferrer) end module Transferrer def transfer_to(destination, amount) self.balance -= amount destination.balance += amount end end end

Slide 19

Slide 19 text

And what about tests? You do write tests, right? RIGHT?!

Slide 20

Slide 20 text

# spec/controllers/transfers_controller_spec.rb (before) describe TransfersController do describe 'POST create' do before(:each) do @s = FactoryGirl.create :account, balance: 500 @d = FactoryGirl.create :account, balance: 1000 end it 'should transfer money between accounts' do post :create, format: :json, source: @s.id, destination: @d.id, amount: 500 # Yikes :-( [ @s, @d ].map(&:reload) expect(response.status).to eq(201) expect(@s.balance).to eq(0) expect(@d.balance).to eq(1500) end end end

Slide 21

Slide 21 text

# spec/contexts/money_transfer_spec.rb (after DCI) describe MoneyTransfer do ! before(:each) do ! ! @source = OpenStruct.new(balance: 500) ! ! @destination = OpenStruct.new(balance: 1000) ! end ! ! it 'should move money between accounts' do ! ! MoneyTransfer.new(@source,@destination).execute(500) ! ! ! ! expect(@source.balance).to eq(0) ! ! expect(@destination.balance).to eq(1500) ! end end

Slide 22

Slide 22 text

Advantages Keeps the model slim (fat != obese) Business logic is easy to find and track down Facilitates reusability Highly testable

Slide 23

Slide 23 text

FUD Object#extend kills kittens

Slide 24

Slide 24 text

FUD Concerns do the exact same thing It’s not real OO Makes you write more code

Slide 25

Slide 25 text

Questions?

Slide 26

Slide 26 text

No content