69
An Introduction of Interator Pattern with Ruby @ ConFoo Montreal 2018-03-07 by Jian Weihang An Introduction of Interator Pattern in Ruby 1

An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

  • Upload
    others

  • View
    2

  • Download
    0

Embed Size (px)

Citation preview

Page 1: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

An Introduction ofInterator Pattern with

Ruby@ ConFoo Montreal 2018-03-07

by Jian Weihang

An Introduction of Interator Pattern in Ruby 1

Page 2: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

Bonjour!An Introduction of Interator Pattern in Ruby 2

Page 3: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

墋簏膠Jian Weihang

An Introduction of Interator Pattern in Ruby 3

Page 4: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

@tonytonyjan

An Introduction of Interator Pattern in Ruby 4

Page 5: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

Taiwan

An Introduction of Interator Pattern in Ruby 5

Page 6: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

An Introduction of Interator Pattern in Ruby 6

Page 7: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

An Introduction of Interator Pattern in Ruby 7

Page 8: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

An Introduction of Interator Pattern in Ruby 8

Page 9: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

$ gem install taiwan

An Introduction of Interator Pattern in Ruby 9

Page 10: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

Tech Leader

An Introduction of Interator Pattern in Ruby 10

Page 11: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

Ruby Developersince 2010

An Introduction of Interator Pattern in Ruby 11

Page 12: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

Maintainerof exif and jaro_winkler

An Introduction of Interator Pattern in Ruby 12

Page 13: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

Published a bookin 2015

An Introduction of Interator Pattern in Ruby 13

Page 14: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

An Introduction of Interator Pattern in

Ruby

An Introduction of Interator Pattern in Ruby 14

Page 15: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

Outline

An Introduction of Interator Pattern in Ruby 15

Page 16: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

An Introduction of Interator Pattern in Ruby 16

Page 17: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

!̴̴

An Introduction of Interator Pattern in Ruby 17

Page 18: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

An Introduction of Interator Pattern in Ruby 18

Page 19: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

How to Help Controllers Lose

Weight?

An Introduction of Interator Pattern in Ruby 19

Page 20: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

The Controller Is a Translator

An Introduction of Interator Pattern in Ruby 20

Page 21: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

Good Practiceclass PostsController < ApplicationController def create @post = Post.create(post_params) redirect_to @post rescue render :new endend

An Introduction of Interator Pattern in Ruby 21

Page 22: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

Bad Practiceclass PostsController < ApplicationController def create @post = Post.create(post_params) @post.send_notification redirect_to @post rescue render :new endend

An Introduction of Interator Pattern in Ruby 22

Page 23: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

!̴̴

An Introduction of Interator Pattern in Ruby 23

Page 24: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

Fat Models andSkinny Controllers

An Introduction of Interator Pattern in Ruby 24

Page 25: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

Single Responsibility Principle

An Introduction of Interator Pattern in Ruby 25

Page 26: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

# Rails 5.1.5class Post < ActiveRecord::Baseend

Post.new.public_methods.size # => 404

An Introduction of Interator Pattern in Ruby 26

Page 27: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

class AlmightyGod < ActiveRecord::Base # hundreds of methodsend

An Introduction of Interator Pattern in Ruby 27

Page 28: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

class Cart < ApplicationModel def add_product(product) endend

vs.class Product < ApplicationModel def add_to_cart(cart) endend

An Introduction of Interator Pattern in Ruby 28

Page 29: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

class Course def add_student(student) endend

vs.class Student def join_course(course) endend

An Introduction of Interator Pattern in Ruby 29

Page 30: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

!̴̴

An Introduction of Interator Pattern in Ruby 30

Page 31: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

Model is neither a class nor object.

An Introduction of Interator Pattern in Ruby 31

Page 32: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

Model is a layer.

An Introduction of Interator Pattern in Ruby 32

Page 33: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

Separation of Concerns• Presentation Layer

• views

• controllers

• Model Layer

• models

An Introduction of Interator Pattern in Ruby 33

Page 34: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

Model Layer

• Domain Objects

• Storage Abstractions

• Services

An Introduction of Interator Pattern in Ruby 34

Page 35: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

Model Layer

• Domain Objects

• Storage Abstractions

• Services

An Introduction of Interator Pattern in Ruby 35

Page 36: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

Model Layer

• Domain Objects

• Storage Abstractions

• Services

An Introduction of Interator Pattern in Ruby 36

Page 37: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

Model Layer

• Domain Objects

• Storage Abstractions

• Services

An Introduction of Interator Pattern in Ruby 37

Page 38: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

Model Layer• ActiveRecord::Base

• Domain Objects

• Storage Abstractions

• Services

• ???

An Introduction of Interator Pattern in Ruby 38

Page 39: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

What about the Implementation

!

An Introduction of Interator Pattern in Ruby 39

Page 40: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

Service Object• a.k.a.

• Interactor

• Use Case

An Introduction of Interator Pattern in Ruby 40

Page 41: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

Clean Architecture

https://goo.gl/ihgHGBAn Introduction of Interator Pattern in Ruby 41

Page 42: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

Minimal Implementation# app/{services|interactors|use_cases}class AddToCart attr_reader :errors

def initialize(cart, product) @cart, @product = cart, product @errors = [] end

def perform # manipulate @cart, @product and @errors ... end

def success?; @errors.empty? endend

An Introduction of Interator Pattern in Ruby 42

Page 43: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

Usageclass CartController < ApplicationController def add_to_cart product = Product.find(params[:product_id]) add_to_cart = AddToCart.new(current_cart, product) add_to_cart.perform if add_to_cart.successs? # ... else # ... end endend

An Introduction of Interator Pattern in Ruby 43

Page 44: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

Advantages• Skinny Controller

• Easier to Trace Code

• Easier to Write Test

An Introduction of Interator Pattern in Ruby 44

Page 45: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

Advantages• Skinny Controller

• Easier to Trace Code

• Easier to Write Test

An Introduction of Interator Pattern in Ruby 45

Page 46: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

Advantages• Skinny Controller

• Easier to Trace Code

• Easier to Write Test

An Introduction of Interator Pattern in Ruby 46

Page 47: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

Advantages• Skinny Controller

• Easier to Trace Code

• Easier to Write Test

An Introduction of Interator Pattern in Ruby 47

Page 48: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

class AddToCart def initialize(cart, product) @cart, @product = cart, product end

def perform @cart.line_items.push(@product) endend

An Introduction of Interator Pattern in Ruby 48

Page 49: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

gem 'rspec-mocks'

describe AddToCart it 'works' do line_items = double('line_items') cart = double('cart', line_items: line_items) product = double('product')

expect(line_items).to receive(:push).once { product } # expect cart.line_items.push(product)

add_to_cart = AddToCart.new(cart, product) add_to_cart.perform endend

An Introduction of Interator Pattern in Ruby 49

Page 50: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

Abstractionclass Interactor attr_reader :errors

def self.perform(*args) new(*args).tap { |interactor| interactor.perform } end

def perform raise NotImplementedError end

def success? @errors.empty? endend

An Introduction of Interator Pattern in Ruby 50

Page 51: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

Usageclass AddToCart < Interactor def initialize(cart, product) @cart = cart @product = product end

def perform # logic here. endend

An Introduction of Interator Pattern in Ruby 51

Page 52: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

Usageclass CartController < ApplicationController def add_to_cart product = Product.find(params[:product_id]) add_to_cart = AddToCart.perform(current_cart, product) if add_to_cart.successs? # ... else # ... end endend

An Introduction of Interator Pattern in Ruby 52

Page 53: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

!̴̴

An Introduction of Interator Pattern in Ruby 53

Page 54: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

Third-party Gems

An Introduction of Interator Pattern in Ruby 54

Page 55: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

gem "mutations"class UserSignup < Mutations::Command required do string :email, matches: EMAIL_REGEX string :name end

optional do boolean :newsletter_subscribe end

def execute # logic endend

UserSignup.run(params[:user])

An Introduction of Interator Pattern in Ruby 55

Page 56: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

gem "interactor"class AuthenticateUser include Interactor

def call if user = User.authenticate(context.email, context.password) context.user = user context.token = user.secret_token else context.fail!(message: "authenticate_user.failure") end endend

AuthenticateUser.call(params)

An Introduction of Interator Pattern in Ruby 56

Page 57: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

FYI

name stars forks issues closed

mutation 1,127 69 54 79%

interactor 1,919 110 76 87%

An Introduction of Interator Pattern in Ruby 57

Page 58: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

gem "interactor2"class AddToCart < Interactor2 attr_reader :line_item, :cart # should be any attribute you want to expose

def initialize(product, cart) @cart = cart @line_item = cart.line_items.new(product: product) end

def perform unless @line_item.save fail! 'oops' end endend

An Introduction of Interator Pattern in Ruby 58

Page 59: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

gem "interactor2"class AddToCart < Interactor2 include ActiveModel::Validations attr_reader :line_item, :cart # should be any attribute you want to expose

validates :product, :cart, presence: true

def initialize(product, cart) @cart = cart @line_item = cart.line_items.new(product: product) end

def perform unless @line_item.save fail! 'oops' end endend

An Introduction of Interator Pattern in Ruby 59

Page 60: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

https://github.com/tonytonyjan/interactor2/

An Introduction of Interator Pattern in Ruby 60

Page 61: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

Conclusion• Consistent Interface

• Self-explaining

• Context Encapsulation

• Decoupling your domain from your framework

An Introduction of Interator Pattern in Ruby 61

Page 62: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

Conclusion• Consistent Interface

• Self-explaining

• Context Encapsulation

• Decoupling your domain from your framework

An Introduction of Interator Pattern in Ruby 62

Page 63: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

Conclusion• Consistent Interface

• Self-explaining

• Context Encapsulation

• Decoupling your domain from your framework

An Introduction of Interator Pattern in Ruby 63

Page 64: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

Conclusion• Consistent Interface

• Self-explaining

• Context Encapsulation

• Decoupling your domain from your framework

An Introduction of Interator Pattern in Ruby 64

Page 65: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

Conclusion• Consistent Interface

• Self-explaining

• Context Encapsulation

• Decoupling your domain from your framework

An Introduction of Interator Pattern in Ruby 65

Page 66: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

Thanks for Your Listening@tonytonyjan

An Introduction of Interator Pattern in Ruby 66

Page 67: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

References• https://8thlight.com/blog/uncle-bob/2012/08/13/the-clean-

architecture.html

• https://www.wikiwand.com/en/Domain-driven_design

• https://github.com/cypriss/mutations

• https://github.com/collectiveidea/interactor

• https://github.com/tonytonyjan/interactor2

An Introduction of Interator Pattern in Ruby 67

Page 68: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

Q&A

An Introduction of Interator Pattern in Ruby 68

Page 69: An Introduction of Interator Pattern with Ruby...An Introduction of Interator Pattern in Ruby 22 4 4! An Introduction of Interator Pattern in Ruby 23. Fat Models and ... An Introduction

Entity-Boundary-Interactor

An Introduction of Interator Pattern in Ruby 69