Imutabilidade em ruby

mauricioszabo 69 views 34 slides Aug 22, 2018
Slide 1
Slide 1 of 34
Slide 1
1
Slide 2
2
Slide 3
3
Slide 4
4
Slide 5
5
Slide 6
6
Slide 7
7
Slide 8
8
Slide 9
9
Slide 10
10
Slide 11
11
Slide 12
12
Slide 13
13
Slide 14
14
Slide 15
15
Slide 16
16
Slide 17
17
Slide 18
18
Slide 19
19
Slide 20
20
Slide 21
21
Slide 22
22
Slide 23
23
Slide 24
24
Slide 25
25
Slide 26
26
Slide 27
27
Slide 28
28
Slide 29
29
Slide 30
30
Slide 31
31
Slide 32
32
Slide 33
33
Slide 34
34

About This Presentation

Slides da apresentação: https://www.youtube.com/watch?v=2hioq6dohtI&t=2137s


Slide Content

Imutabilidade em Ruby

Bom dia! Maurício Szabo http://mauricio.szabo.link

Imutabilidade? Em Ruby? Por quê?

But Why!? Concorrencia Multi-thread Escalabilidade horizontal Blablabla... Previsibilidade Consistência Replicabilidade Composição Mantenabilidade

Previsibilidade

Consistência age = 18 age = 28 Person 1 Person 2 Task 1 Task 2 Task 3 Task 4

Replicabilidade f(10, 20, 30) 42

Replicabilidade f(10, 20, 30) 42

Replicabilidade rand() 0.01090 f(10, 20, 30)

Replicabilidade rand() 0.92100 f(10, 20, 30)

h Funções Puras rand f g h

Ruby, Finalmente Estruturas de Dados Imutáveis 1 https://bit.ly/2JjCUzE

Estruturas Hamster::Vector[] Hamster::Deque[] Hamster::List[] Hamster::Set[] Hamster::Hash[] Acesso via indice p ush / append p op / drop_last u nshift / prepend shift / tail

Performance? Spoiler: é mais lento!

Lista de Elementos (prepend) real Mutable array - unshift 0.050518 Mutable array - shift 0.028875 Immutable list - unshift 0.342788 (6.8x mais lento) Immutable list - shift 0.028016 (+/- mesma velocidade)

Lista de Elementos real Mutable array - push 0.047483 Mutable array - pop 0.029408 Mutable array - unshift 0.050518 Mutable array - shift 0.028875 Immutable deque - append at last 0.537605 (11x mais lento) Immutable deque - pop 0.179720 (6x mais lento) Immutable deque - append at first 0.496692 (9.5x mais lento) Immutable deque - shift 0.172747 (6x mais lento)

Random Access real Mutable array 0.047483 Mutable array - get random element 0.047016 Mutable array - pop 0.029408 Immutable vector 1.782584 (37x mais lento!!!) Immutable vector - get random element 0.213734 (4.5x mais lento) Immutable vector - pop 4.246951 (144x mais lento!!!)

“Hack” real Mutable array 0.343495 Immutable list - prepend 3.075296 (10x mais lento) Immutable list - from mutable 0.955190 (3.7x mais lento) Immutable Deque - from mutable 0.947304 (3.7x mais lento) Immutable Vector - from mutable 0.299589 (1.8x mais lento)

Objetos ! Trabalhando com instâncias imutáveis 🏈

An object has state (data) and behavior (code) (Wikipedia) Wikipedia is not a reliable source (Every university professor)

class User include Anima . new( :name , :email ) end user = User . new(name: "Foo" , email : "[email protected]" ) user . email << ".br" user . email # => "[email protected]" def user . nada "#{ name } = #{ email }" end user . nada # => "Foo = [email protected]" class User include Anima . new( :name , :email ) include Adamantium end user = User . new(name: "Foo" , email : "[email protected]" ) user . email << ".br" # => can’t modify frozen object def user . nada "#{ name } = #{ email }" e nd # => can’t modify frozen object

class User include Anima . new( :name , :email ) end user = User . new(name: "Foo" , email : "[email protected]" ) user2 = user.with( email : "[email protected]" ) user . email # => "[email protected]" user2 . email # => "[email protected]" Como trabalhar?

Padrões - Data First class User include Anima . new( :name , :children ) include UpInAnima NULL = new (name: "" , children : Hamster : :Vector [] ) end class Children include Anima . new( :name , :age ) include UpInAnima NULL = new (name: "" , age : ) end

Padrões - Data First https://bit.ly/2JjCUzE user = User : :NULL . with(name: "Ariovaldo" ) . update_in( :children ) { | c | c . add( Children : :NULL . with(name: "Emily" , age : 9 )) } # Emily's birthday! user . update_in( :children , , :age ) { | age | age + 1 }

Banco de Dados Datasets imutáveis, Sequel, ROM, ActiveRecord, etc...

Bancos de Dados id = 1 age = 9 id = 1 age = 10 Validate id = 1 age = 10

Either Monad Dados Dados Transformados Dados Transformados’ Erros Erros Erros UPDATE! Validate Dados para Update

Talk is Easy... class User extend Sequel : :Model :: ClassMethods include Anima . new( :id , :name , :email ) self . dataset = DB [ :users ] def self . call (param) new (param) end def update! (params) validate(params) . then do | new_obj | pk = self . class . primary_key pk_value = send(pk) self . class . dataset . where(pk => pk_value) . update(new_obj . to_h) new_obj end end private :with private def validate (params) new_obj = with(params) errors = NameValidation . call(new_obj . to_h) . errors if (errors . empty?) Either . right(new_obj) else Either . left(errors) end end end

class User extend Sequel : :Model :: ClassMethods include Anima . new( :id , :name , :email ) self . dataset = DB [ :users ] def self . call (param) new (param) end # ... end

class User # … private def validate (params) new_obj = with(params) errors = NameValidation . call(new_obj . to_h) . error if (errors . empty?) Either . right(new_obj) else Either . left(errors) end end end

class User # ... def update! (params) validate(params) . then do | new_obj | pk = self . class . primary_key pk_value = send(pk) s elf . class . dataset . where(pk => pk_value) . update(new_obj . to_h) new_obj end E nd private :with # ... end

u2 = u . update!(name: "" ) # => Either left=.... User . first # => #<User id=1 name="Foo Bar" email=nil> u2 = u . update!( email : "[email protected]" ) User . first # => #<User id=1 name="Foo Bar" email="[email protected]"> u2 = u . update!(name: "Szabo" ) User . first # => #<User id=1 name="Szabo" email=nil> u = User . first # => #<User id=1 name="Foo Bar" email=nil>

Transformação Imutável Dado FN Dado Alterado

[]’s Perguntas? Meus links: http://mauricio.szabo.link [email protected] https://bit.ly/2JjCUzE