SlideShare a Scribd company logo
1 of 49
Download to read offline
From The If Jungle to A
Civilised Railway Station
By Botond Orban
About Me
Botond Orban Enthusiast IT Guy, Architect 

Enthusiastic about Ruby

https://github.com/orbanbotond

@orbanbotond
The Origins
The PC made in Ukraine
Code can be written
in a better way!
Railway Oriented Development
With 3 libraries in Parallel!
-classic if jungle
-dry transactions
-monad do notation
-trailblazer operations
def create
user = User.create user_params[:user]
if user.valid?
package = Package.create package_params[:user]
if package.valid?
user.package = package
user.save
SmsService.send_registration_msg(user, package)
EmailService.send_registration_msg(user, package)
SystemNotifierService.send_registration_msg(user,
package)
else
render ...
end
else
render ...
end
end
True If Jungle
Cyclomatic complexity: 2
def create
user = User.create user_params[:user]
if user.valid?
package = Package.create package_params[:user]
if package.valid?
package.user = user
package.save
if params[:coupon].present?
if coupon = Coupon.exists? params[:coupon]
discount = Discount.create params[:coupon]
package.discount = discount
package.save
else
render …
end
end
SmsService.send_registration_msg(user, package)
EmailService.send_registration_msg(user, package)
SystemNotifierService.send_registration_msg(user, package)
else
render ...
end
else
render ...
end
end
True If Jungle
Cyclomatic complexity: 4
True If Jungle
def create
user = User.create user_params[:user]
if user.valid?
package = Package.create package_params[:user]
if package.valid?
package.user = user
package.save
if params[:coupon].present?
if Coupon.exists? params[:coupon]
discount = Discount.create params[:coupon]
if discount.allowsUser? user
package.discount = discount
package.save
else
render ...
end
else
render ...
end
end
SmsService.send_registration_msg(user, package)
EmailService.send_registration_msg(user, package)
SystemNotifierService.send_registration_msg(user, package)
else
render ...
end
else
render ...
end
end
Cyclomatic complexity: 5
Example 1
f(x) = ax+b
No Library
If Jungle
If Jungle Implementation
Specs:
f(a,b) = a+b, a is infinite
context 'add' do
subject { add.call params: params }


context 'negative cases' do
context 'params infinite' do
let(:params) { [(1.0/0.0), 2] }
specify 'Be a failure with a proper error
message' do
expect(subject[:validation]).to eq 'must
be a real number'
end
end
end
add = ->(params:) do
return { validation: 'must be a real
number' } if params.any?{|x|x.infinite?}
end
Code:
If Jungle Implementation
f(a,b) = a+b, a is infinite
Specs:
context 'add' do
subject { add.call params: params }
let(:params) { [2,3,4] }
context 'negative cases' do …
context 'positive cases' do
specify 'Be a success with the proper correct
output' do
expect(subject[:operation_result]).to
eq(params.reduce(0) { |acc, x| acc + x })
end
end
end
If Jungle Implementation
f(a,b) = a+b,
Code:
add = ->(params:) do
return { validation: 'must be a real
number' } if params.any?{|x|x.infinite?}
result = params.reduce(0) { |acc, x| acc
+ x }
return { operation_result: result }
end
If Jungle Implementation
f(a,b) = a+b,
linear_function = ->(params:) do
result = multiply.call(params: params[-2..-1])
if(result[:operation_result])
return add.call(params:
[result[:operation_result], params[0]])
else
return result
end
end
rspec spec/railway_oriented_development/if_jungle_spec.rb
.......
7 examples, 0 failures
If Jungle Implementation
f(a,b,x) = a.x+b, Linear function
Building Blocks
Add Operation

-Guard Condition

-Business Logic: +

Multiply Operation

-Guard Condition

-Business Logic: *

LinearFunction

-Delegation

-Conditional

-Delegation

-Return a Result
If Jungle Implementation
1st library
Dry Transactions
Specs:
context 'add' do
subject { DryTransactions::Add.new.call params }


context 'negative cases' do
context 'params infinite' do
let(:params) { {params:[(1.0/0.0), 2]} }
specify 'Be a failure with a proper error
message' do
expect(subject).to be_failure
expect(subject.failure).to eq 'must be a
real number'
end
end
end
Dry Transactions
f(a,b) = a+b, a is infinite
Code:
module DryTransactions
class Add
include Dry::Transaction
step :validate
step :add
private
…
…
Dry Transactions
f(a,b) = a+b, a is infinite
Railway Oriented Approach
Code:
module DryTransactions
class Add
…
private
def validate(input)
return Failure('must be a real number') unless input.all?{|x|
x.finite?}
Success(input)
end

def add(input)
ret = input.reduce(0) { |acc, x| acc + x }
Success(ret)
end
…
Dry Transactions
f(a,b) = a+b, a is infinite
class LinearOperation
include Dry::Transaction
# a*x
step :multiply
# previous_result + b
step :assembling_partial_results
private
…
end
Dry Transactions
f(a, b, x) = a.x+b, Linear Function
class ComplexOperation
include Dry::Transaction
…
def multiply(input)
partialValue = Multiply.new.call(params: [input[:params]
[1], input[:params][2]])
partialValue.bind do |value|
Success(input.merge(multiplication_result:
partialValue.value!))
end
end
def assembling_partial_results(input)
Add.new.call( params: [input[:params][0],
input[:multiplication_result]])
end
end
rspec spec/railway_oriented_development/dry_transactions_spec.rb
.......
7 examples, 0 failures
Dry Transactions
f(a, b, x) = a.x+b, a is infinite
Dry Transaction Implementation
Add Operation

-Guard Step

-Business Logic Step: +

Multiply Operation

-Guard Step

-Business Step: *

LinearFunction

-Multiply Step

-Assemble Step

Note: 

-no conditional compared to the If Jungle Solution!

-linear execution by enlisting the steps!
2rd library
Monad Do Notation
Specs:
context 'add' do
subject { MonadDoNotation::Add.new.call params }


context 'negative cases' do
context 'params infinite' do
let(:params) { [(1.0/0.0), 2] }
specify 'Be a failure with a proper error
message' do
expect(subject).to be_failure
expect(subject.failure[:validation]).to eq
'must be a real number'
end
end
end
Monad Do Notation
f(a,b) = a+b, a is infinite
Code:
class Add
include Dry::Monads::Result::Mixin
include Dry::Monads::Do::All
def call(arguments)
validation_result = yield validate(arguments)
operation_result = yield add(arguments)
Success validation_result.merge( operation_result)
end
…
end
Monad Do Notation
f(a,b) = a+b, a is infinite
Code:
class Add
…
def validate(input)
return Failure(validation: 'must be a real
number') unless input.all?{|x|x.finite?}
Success(validation: :ok)
end
def add(input)
ret = input.reduce(0) { |acc, x| acc + x }
Success(operation_result: ret)
end
end
…
Monad Do Notation
f(a,b) = a+b, a is infinite
class LinearOperation
include Dry::Monads::Result::Mixin
include Dry::Monads::Do::All
def call(input)
multiplication = yield
multiply(input[-2..-1])
addition = yield add([input[0],
multiplication[:operation_result]])
Success(addition)
end
private …
Monad Do Notation
f(a, b, x) = a.x+b,
class LinearOperation
include Dry::Monads::Result::Mixin
include Dry::Monads::Do::All
…
private
def multiply(args)
Multiply.new.call args
end
def add(args)
Add.new.call args
end
end
rspec spec/railway_oriented_development/monad_do_notation_spec.rb
.......
7 examples, 0 failures
Monad Do Notation
f(a, b, x) = a.x+b,
Add Operation

-Validate Method

-Business Logic Method: +

Multiply Operation

-Validate Method

-Business Logic Method: *

LinearFunction

-Multiply Method

-Add Method Step

Note: 

-no conditional compared to the If Jungle Solution!

-linear execution!

-pure Ruby! *****

Monad Do Notation Implementation
3rd library
Trailblazer Operations
Specs:
context 'add' do
subject { TrailblazerOperations::Add.call params: params }


context 'negative cases' do
context 'params infinite' do
let(:params) { [(1.0/0.0), 2] }
specify 'Be a failure with a proper error message' do
expect(subject).to be_failure
expect(subject[:validation]).to eq 'must be a real
number'
end
end
end
Trailblazer Operations
f(a,b) = a+b, a is infinite
Code:
module TrailblazerOperations
class Add < Trailblazer::Operation
step :validate
step :add
private
…
end
End
Trailblazer Operations
f(a,b) = a+b, a is infinite
Railway Oriented Approach
Code:
module TrailblazerOperations
class Add < Trailblazer::Operation
…
private
def validate(options, params:)
unless params.all?{|x|x.finite?}
options[:validation] = 'must be a real number'
return Railway.fail!
end
Railway.pass!
end
def add(options, params:, **rest)
ret = params.reduce(0) { |acc, x| acc + x }
options[:operation_result] = ret
end
end
end
end
Code:
class LinearOperation < Trailblazer::Operation
step Nested( Multiply,
input: -> (options, params:, **) do
options.merge params: params[-2..-1]
end
)
step Nested( Add,
input: -> (options, params:, **) do
options.to_hash.except(:operation_result).merge
params: [params[0], options[:operation_result]]
end
)
end
rspec spec/railway_oriented_development/trailblazer_operations_spec.rb
.......
7 examples, 0 failures
Trailblazer Operations
f(a, b, x) = a.x+b,
Add Operation

-Validate Step

-Business Logic Step: +

Multiply Operation

-Validate Step

-Business Logic Step: *

LinearFunction

-Delegates to the Multiply Operation by Nesting

-Delegates to the Add Operation by Nesting

Note:

-no conditional compared to the If Jungle Solution!

-linear execution!

-DSL for reuse!

Trailblazer Implementation
Dry-Transaction Monad Do Notation Trailblazer
Steps Steps
Ruby Code Wrapped
With Yield
Steps
Code Reuse Ruby Call
Ruby Code Wrapped
With Yield
DSL for other
Operation Reuse!
True If Jungle
def create
user = User.create user_params[:user]
if user.valid?
package = Package.create package_params[:user]
if package.valid?
package.user = user
package.save
if params[:coupon].present?
if Coupon.exists? params[:coupon]
discount = Discount.create params[:coupon]
if discount.allowsUser? user
package.discount = discount
package.save
else
render ...
end
else
render ...
end
end
SmsService.send_registration_msg(user, package)
EmailService.send_registration_msg(user, package)
SystemNotifierService.send_registration_msg(user, package)
else
render ...
end
else
render ...
end
end
Cyclomatic complexity: 5
Railway Oriented Development
Cyclomatic complexity: 1-2
class Add < Trailblazer::Operation
step :persist_user
step :persist_package
step :add_coupon_based_discount
step :notify_about_registration
...
end
Railway Oriented Development
Cyclomatic complexity: 1-2
class Add < Trailblazer::Operation
step :persist_user
failure :log_user_persistance
step :persist_package
failure :log_package_persistance
step :add_coupon_based_discount
failure :log_discount_creation
step :notify_about_registration
...
end
Railway Oriented Development
Cyclomatic complexity: 1-2
class Add < Trailblazer::Operation
step :persist_user
failure :log_user_persistance
step :persist_package
failure :log_package_persistance
step :add_coupon_based_discount
failure :log_discount_creation
step :notify_about_registration
step :notify_facebook_friends
…
end
Contract for every input (entity & other use case)



Basement:

-Operations for CRUD



Crud (and Other) Reuse (DRY):

-Operations for Onboarding

-Operations for Admin

-Operations for handling Business Use Cases
Trailblazer Operations & Contracts (Reform)
My Best Practice
Thank you ;)
Botond Orban Enthusiast IT Guy, Architect 

Enthusiastic about Ruby

https://github.com/orbanbotond

@orbanbotond

More Related Content

What's hot

What's hot (20)

Computer Programming- Lecture 6
Computer Programming- Lecture 6Computer Programming- Lecture 6
Computer Programming- Lecture 6
 
C++ L06-Pointers
C++ L06-PointersC++ L06-Pointers
C++ L06-Pointers
 
Ch7 C++
Ch7 C++Ch7 C++
Ch7 C++
 
Let's make a contract: the art of designing a Java API
Let's make a contract: the art of designing a Java APILet's make a contract: the art of designing a Java API
Let's make a contract: the art of designing a Java API
 
C++ Presentation
C++ PresentationC++ Presentation
C++ Presentation
 
Functions123
Functions123 Functions123
Functions123
 
Functions12
Functions12Functions12
Functions12
 
Svitla talks 2021_03_25
Svitla talks 2021_03_25Svitla talks 2021_03_25
Svitla talks 2021_03_25
 
Computer Programming- Lecture 3
Computer Programming- Lecture 3Computer Programming- Lecture 3
Computer Programming- Lecture 3
 
C++ Language
C++ LanguageC++ Language
C++ Language
 
User defined functions
User defined functionsUser defined functions
User defined functions
 
C++ L05-Functions
C++ L05-FunctionsC++ L05-Functions
C++ L05-Functions
 
Programming python quick intro for schools
Programming python quick intro for schoolsProgramming python quick intro for schools
Programming python quick intro for schools
 
Computer Programming- Lecture 7
Computer Programming- Lecture 7Computer Programming- Lecture 7
Computer Programming- Lecture 7
 
Falcon初印象
Falcon初印象Falcon初印象
Falcon初印象
 
Resource wrappers in C++
Resource wrappers in C++Resource wrappers in C++
Resource wrappers in C++
 
C++ L10-Inheritance
C++ L10-InheritanceC++ L10-Inheritance
C++ L10-Inheritance
 
Part 3-functions
Part 3-functionsPart 3-functions
Part 3-functions
 
Computer Programming- Lecture 10
Computer Programming- Lecture 10Computer Programming- Lecture 10
Computer Programming- Lecture 10
 
Computer Programming- Lecture 8
Computer Programming- Lecture 8Computer Programming- Lecture 8
Computer Programming- Lecture 8
 

Similar to The Trailblazer Ride from the If Jungle into a Civilised Railway Station - Orban Botond (ENG) | Ruby Meditation 27

Hermes2D FEM Library
Hermes2D FEM LibraryHermes2D FEM Library
Hermes2D FEM LibraryLukas Korous
 
Things about Functional JavaScript
Things about Functional JavaScriptThings about Functional JavaScript
Things about Functional JavaScriptChengHui Weng
 
What's new in Python 3.11
What's new in Python 3.11What's new in Python 3.11
What's new in Python 3.11Henry Schreiner
 
Introducing Middy, Node.js middleware engine for AWS Lambda (FrontConf Munich...
Introducing Middy, Node.js middleware engine for AWS Lambda (FrontConf Munich...Introducing Middy, Node.js middleware engine for AWS Lambda (FrontConf Munich...
Introducing Middy, Node.js middleware engine for AWS Lambda (FrontConf Munich...Luciano Mammino
 
Use Applicative where applicable!
Use Applicative where applicable!Use Applicative where applicable!
Use Applicative where applicable!Hermann Hueck
 
ForLoopandUserDefinedFunctions.pptx
ForLoopandUserDefinedFunctions.pptxForLoopandUserDefinedFunctions.pptx
ForLoopandUserDefinedFunctions.pptxAaliyanShaikh
 
Geeks Anonymes - Le langage Go
Geeks Anonymes - Le langage GoGeeks Anonymes - Le langage Go
Geeks Anonymes - Le langage GoGeeks Anonymes
 
Introduction to functional programming using Ocaml
Introduction to functional programming using OcamlIntroduction to functional programming using Ocaml
Introduction to functional programming using Ocamlpramode_ce
 
What's New In Python 2.5
What's New In Python 2.5What's New In Python 2.5
What's New In Python 2.5Richard Jones
 
The Road To Monad Transformers
The Road To Monad TransformersThe Road To Monad Transformers
The Road To Monad TransformersPawel Lisewski
 
Promises - Asynchronous Control Flow
Promises - Asynchronous Control FlowPromises - Asynchronous Control Flow
Promises - Asynchronous Control FlowHenrique Barcelos
 
Столпы функционального программирования для адептов ООП, Николай Мозговой
Столпы функционального программирования для адептов ООП, Николай МозговойСтолпы функционального программирования для адептов ООП, Николай Мозговой
Столпы функционального программирования для адептов ООП, Николай МозговойSigma Software
 
Zope component architechture
Zope component architechtureZope component architechture
Zope component architechtureAnatoly Bubenkov
 
Functional programming ii
Functional programming iiFunctional programming ii
Functional programming iiPrashant Kalkar
 
Python lambda functions with filter, map & reduce function
Python lambda functions with filter, map & reduce functionPython lambda functions with filter, map & reduce function
Python lambda functions with filter, map & reduce functionARVIND PANDE
 
golang_getting_started.pptx
golang_getting_started.pptxgolang_getting_started.pptx
golang_getting_started.pptxGuy Komari
 
Rubinius @ RubyAndRails2010
Rubinius @ RubyAndRails2010Rubinius @ RubyAndRails2010
Rubinius @ RubyAndRails2010Dirkjan Bussink
 

Similar to The Trailblazer Ride from the If Jungle into a Civilised Railway Station - Orban Botond (ENG) | Ruby Meditation 27 (20)

Hermes2D FEM Library
Hermes2D FEM LibraryHermes2D FEM Library
Hermes2D FEM Library
 
Things about Functional JavaScript
Things about Functional JavaScriptThings about Functional JavaScript
Things about Functional JavaScript
 
What's new in Python 3.11
What's new in Python 3.11What's new in Python 3.11
What's new in Python 3.11
 
MP in Clojure
MP in ClojureMP in Clojure
MP in Clojure
 
Introducing Middy, Node.js middleware engine for AWS Lambda (FrontConf Munich...
Introducing Middy, Node.js middleware engine for AWS Lambda (FrontConf Munich...Introducing Middy, Node.js middleware engine for AWS Lambda (FrontConf Munich...
Introducing Middy, Node.js middleware engine for AWS Lambda (FrontConf Munich...
 
Use Applicative where applicable!
Use Applicative where applicable!Use Applicative where applicable!
Use Applicative where applicable!
 
ForLoopandUserDefinedFunctions.pptx
ForLoopandUserDefinedFunctions.pptxForLoopandUserDefinedFunctions.pptx
ForLoopandUserDefinedFunctions.pptx
 
Geeks Anonymes - Le langage Go
Geeks Anonymes - Le langage GoGeeks Anonymes - Le langage Go
Geeks Anonymes - Le langage Go
 
functions
functionsfunctions
functions
 
Introduction to functional programming using Ocaml
Introduction to functional programming using OcamlIntroduction to functional programming using Ocaml
Introduction to functional programming using Ocaml
 
What's New In Python 2.5
What's New In Python 2.5What's New In Python 2.5
What's New In Python 2.5
 
The Road To Monad Transformers
The Road To Monad TransformersThe Road To Monad Transformers
The Road To Monad Transformers
 
Promises - Asynchronous Control Flow
Promises - Asynchronous Control FlowPromises - Asynchronous Control Flow
Promises - Asynchronous Control Flow
 
Столпы функционального программирования для адептов ООП, Николай Мозговой
Столпы функционального программирования для адептов ООП, Николай МозговойСтолпы функционального программирования для адептов ООП, Николай Мозговой
Столпы функционального программирования для адептов ООП, Николай Мозговой
 
Zope component architechture
Zope component architechtureZope component architechture
Zope component architechture
 
Chapter 02 functions -class xii
Chapter 02   functions -class xiiChapter 02   functions -class xii
Chapter 02 functions -class xii
 
Functional programming ii
Functional programming iiFunctional programming ii
Functional programming ii
 
Python lambda functions with filter, map & reduce function
Python lambda functions with filter, map & reduce functionPython lambda functions with filter, map & reduce function
Python lambda functions with filter, map & reduce function
 
golang_getting_started.pptx
golang_getting_started.pptxgolang_getting_started.pptx
golang_getting_started.pptx
 
Rubinius @ RubyAndRails2010
Rubinius @ RubyAndRails2010Rubinius @ RubyAndRails2010
Rubinius @ RubyAndRails2010
 

More from Ruby Meditation

Is this Legacy or Revenant Code? - Sergey Sergyenko | Ruby Meditation 30
Is this Legacy or Revenant Code? - Sergey Sergyenko  | Ruby Meditation 30Is this Legacy or Revenant Code? - Sergey Sergyenko  | Ruby Meditation 30
Is this Legacy or Revenant Code? - Sergey Sergyenko | Ruby Meditation 30Ruby Meditation
 
Life with GraphQL API: good practices and unresolved issues - Roman Dubrovsky...
Life with GraphQL API: good practices and unresolved issues - Roman Dubrovsky...Life with GraphQL API: good practices and unresolved issues - Roman Dubrovsky...
Life with GraphQL API: good practices and unresolved issues - Roman Dubrovsky...Ruby Meditation
 
Where is your license, dude? - Viacheslav Miroshnychenko | Ruby Meditation 29
Where is your license, dude? - Viacheslav Miroshnychenko | Ruby Meditation 29Where is your license, dude? - Viacheslav Miroshnychenko | Ruby Meditation 29
Where is your license, dude? - Viacheslav Miroshnychenko | Ruby Meditation 29Ruby Meditation
 
Dry-validation update. Dry-validation vs Dry-schema 1.0 - Aleksandra Stolyar ...
Dry-validation update. Dry-validation vs Dry-schema 1.0 - Aleksandra Stolyar ...Dry-validation update. Dry-validation vs Dry-schema 1.0 - Aleksandra Stolyar ...
Dry-validation update. Dry-validation vs Dry-schema 1.0 - Aleksandra Stolyar ...Ruby Meditation
 
How to cook Rabbit on Production - Bohdan Parshentsev | Ruby Meditation 28
How to cook Rabbit on Production - Bohdan Parshentsev | Ruby Meditation 28 How to cook Rabbit on Production - Bohdan Parshentsev | Ruby Meditation 28
How to cook Rabbit on Production - Bohdan Parshentsev | Ruby Meditation 28 Ruby Meditation
 
How to cook Rabbit on Production - Serhiy Nazarov | Ruby Meditation 28
How to cook Rabbit on Production - Serhiy Nazarov | Ruby Meditation 28How to cook Rabbit on Production - Serhiy Nazarov | Ruby Meditation 28
How to cook Rabbit on Production - Serhiy Nazarov | Ruby Meditation 28Ruby Meditation
 
Reinventing the wheel - why do it and how to feel good about it - Julik Tarkh...
Reinventing the wheel - why do it and how to feel good about it - Julik Tarkh...Reinventing the wheel - why do it and how to feel good about it - Julik Tarkh...
Reinventing the wheel - why do it and how to feel good about it - Julik Tarkh...Ruby Meditation
 
Performance Optimization 101 for Ruby developers - Nihad Abbasov (ENG) | Ruby...
Performance Optimization 101 for Ruby developers - Nihad Abbasov (ENG) | Ruby...Performance Optimization 101 for Ruby developers - Nihad Abbasov (ENG) | Ruby...
Performance Optimization 101 for Ruby developers - Nihad Abbasov (ENG) | Ruby...Ruby Meditation
 
Use cases for Serverless Technologies - Ruslan Tolstov (RUS) | Ruby Meditatio...
Use cases for Serverless Technologies - Ruslan Tolstov (RUS) | Ruby Meditatio...Use cases for Serverless Technologies - Ruslan Tolstov (RUS) | Ruby Meditatio...
Use cases for Serverless Technologies - Ruslan Tolstov (RUS) | Ruby Meditatio...Ruby Meditation
 
What/How to do with GraphQL? - Valentyn Ostakh (ENG) | Ruby Meditation 27
What/How to do with GraphQL? - Valentyn Ostakh (ENG) | Ruby Meditation 27What/How to do with GraphQL? - Valentyn Ostakh (ENG) | Ruby Meditation 27
What/How to do with GraphQL? - Valentyn Ostakh (ENG) | Ruby Meditation 27Ruby Meditation
 
New features in Rails 6 - Nihad Abbasov (RUS) | Ruby Meditation 26
New features in Rails 6 -  Nihad Abbasov (RUS) | Ruby Meditation 26New features in Rails 6 -  Nihad Abbasov (RUS) | Ruby Meditation 26
New features in Rails 6 - Nihad Abbasov (RUS) | Ruby Meditation 26Ruby Meditation
 
Security Scanning Overview - Tetiana Chupryna (RUS) | Ruby Meditation 26
Security Scanning Overview - Tetiana Chupryna (RUS) | Ruby Meditation 26Security Scanning Overview - Tetiana Chupryna (RUS) | Ruby Meditation 26
Security Scanning Overview - Tetiana Chupryna (RUS) | Ruby Meditation 26Ruby Meditation
 
Teach your application eloquence. Logs, metrics, traces - Dmytro Shapovalov (...
Teach your application eloquence. Logs, metrics, traces - Dmytro Shapovalov (...Teach your application eloquence. Logs, metrics, traces - Dmytro Shapovalov (...
Teach your application eloquence. Logs, metrics, traces - Dmytro Shapovalov (...Ruby Meditation
 
Best practices. Exploring - Ike Kurghinyan (RUS) | Ruby Meditation 26
Best practices. Exploring - Ike Kurghinyan (RUS) | Ruby Meditation 26Best practices. Exploring - Ike Kurghinyan (RUS) | Ruby Meditation 26
Best practices. Exploring - Ike Kurghinyan (RUS) | Ruby Meditation 26Ruby Meditation
 
Road to A/B testing - Alexey Vasiliev (ENG) | Ruby Meditation 25
Road to A/B testing - Alexey Vasiliev (ENG) | Ruby Meditation 25Road to A/B testing - Alexey Vasiliev (ENG) | Ruby Meditation 25
Road to A/B testing - Alexey Vasiliev (ENG) | Ruby Meditation 25Ruby Meditation
 
Concurrency in production. Real life example - Dmytro Herasymuk | Ruby Medita...
Concurrency in production. Real life example - Dmytro Herasymuk | Ruby Medita...Concurrency in production. Real life example - Dmytro Herasymuk | Ruby Medita...
Concurrency in production. Real life example - Dmytro Herasymuk | Ruby Medita...Ruby Meditation
 
Data encryption for Ruby web applications - Dmytro Shapovalov (RUS) | Ruby Me...
Data encryption for Ruby web applications - Dmytro Shapovalov (RUS) | Ruby Me...Data encryption for Ruby web applications - Dmytro Shapovalov (RUS) | Ruby Me...
Data encryption for Ruby web applications - Dmytro Shapovalov (RUS) | Ruby Me...Ruby Meditation
 
Rails App performance at the limit - Bogdan Gusiev
Rails App performance at the limit - Bogdan GusievRails App performance at the limit - Bogdan Gusiev
Rails App performance at the limit - Bogdan GusievRuby Meditation
 
GDPR. Next Y2K in 2018? - Anton Tkachov | Ruby Meditation #23
GDPR. Next Y2K in 2018? - Anton Tkachov | Ruby Meditation #23GDPR. Next Y2K in 2018? - Anton Tkachov | Ruby Meditation #23
GDPR. Next Y2K in 2018? - Anton Tkachov | Ruby Meditation #23Ruby Meditation
 
Postgres vs Elasticsearch while enriching data - Vlad Somov | Ruby Meditaiton...
Postgres vs Elasticsearch while enriching data - Vlad Somov | Ruby Meditaiton...Postgres vs Elasticsearch while enriching data - Vlad Somov | Ruby Meditaiton...
Postgres vs Elasticsearch while enriching data - Vlad Somov | Ruby Meditaiton...Ruby Meditation
 

More from Ruby Meditation (20)

Is this Legacy or Revenant Code? - Sergey Sergyenko | Ruby Meditation 30
Is this Legacy or Revenant Code? - Sergey Sergyenko  | Ruby Meditation 30Is this Legacy or Revenant Code? - Sergey Sergyenko  | Ruby Meditation 30
Is this Legacy or Revenant Code? - Sergey Sergyenko | Ruby Meditation 30
 
Life with GraphQL API: good practices and unresolved issues - Roman Dubrovsky...
Life with GraphQL API: good practices and unresolved issues - Roman Dubrovsky...Life with GraphQL API: good practices and unresolved issues - Roman Dubrovsky...
Life with GraphQL API: good practices and unresolved issues - Roman Dubrovsky...
 
Where is your license, dude? - Viacheslav Miroshnychenko | Ruby Meditation 29
Where is your license, dude? - Viacheslav Miroshnychenko | Ruby Meditation 29Where is your license, dude? - Viacheslav Miroshnychenko | Ruby Meditation 29
Where is your license, dude? - Viacheslav Miroshnychenko | Ruby Meditation 29
 
Dry-validation update. Dry-validation vs Dry-schema 1.0 - Aleksandra Stolyar ...
Dry-validation update. Dry-validation vs Dry-schema 1.0 - Aleksandra Stolyar ...Dry-validation update. Dry-validation vs Dry-schema 1.0 - Aleksandra Stolyar ...
Dry-validation update. Dry-validation vs Dry-schema 1.0 - Aleksandra Stolyar ...
 
How to cook Rabbit on Production - Bohdan Parshentsev | Ruby Meditation 28
How to cook Rabbit on Production - Bohdan Parshentsev | Ruby Meditation 28 How to cook Rabbit on Production - Bohdan Parshentsev | Ruby Meditation 28
How to cook Rabbit on Production - Bohdan Parshentsev | Ruby Meditation 28
 
How to cook Rabbit on Production - Serhiy Nazarov | Ruby Meditation 28
How to cook Rabbit on Production - Serhiy Nazarov | Ruby Meditation 28How to cook Rabbit on Production - Serhiy Nazarov | Ruby Meditation 28
How to cook Rabbit on Production - Serhiy Nazarov | Ruby Meditation 28
 
Reinventing the wheel - why do it and how to feel good about it - Julik Tarkh...
Reinventing the wheel - why do it and how to feel good about it - Julik Tarkh...Reinventing the wheel - why do it and how to feel good about it - Julik Tarkh...
Reinventing the wheel - why do it and how to feel good about it - Julik Tarkh...
 
Performance Optimization 101 for Ruby developers - Nihad Abbasov (ENG) | Ruby...
Performance Optimization 101 for Ruby developers - Nihad Abbasov (ENG) | Ruby...Performance Optimization 101 for Ruby developers - Nihad Abbasov (ENG) | Ruby...
Performance Optimization 101 for Ruby developers - Nihad Abbasov (ENG) | Ruby...
 
Use cases for Serverless Technologies - Ruslan Tolstov (RUS) | Ruby Meditatio...
Use cases for Serverless Technologies - Ruslan Tolstov (RUS) | Ruby Meditatio...Use cases for Serverless Technologies - Ruslan Tolstov (RUS) | Ruby Meditatio...
Use cases for Serverless Technologies - Ruslan Tolstov (RUS) | Ruby Meditatio...
 
What/How to do with GraphQL? - Valentyn Ostakh (ENG) | Ruby Meditation 27
What/How to do with GraphQL? - Valentyn Ostakh (ENG) | Ruby Meditation 27What/How to do with GraphQL? - Valentyn Ostakh (ENG) | Ruby Meditation 27
What/How to do with GraphQL? - Valentyn Ostakh (ENG) | Ruby Meditation 27
 
New features in Rails 6 - Nihad Abbasov (RUS) | Ruby Meditation 26
New features in Rails 6 -  Nihad Abbasov (RUS) | Ruby Meditation 26New features in Rails 6 -  Nihad Abbasov (RUS) | Ruby Meditation 26
New features in Rails 6 - Nihad Abbasov (RUS) | Ruby Meditation 26
 
Security Scanning Overview - Tetiana Chupryna (RUS) | Ruby Meditation 26
Security Scanning Overview - Tetiana Chupryna (RUS) | Ruby Meditation 26Security Scanning Overview - Tetiana Chupryna (RUS) | Ruby Meditation 26
Security Scanning Overview - Tetiana Chupryna (RUS) | Ruby Meditation 26
 
Teach your application eloquence. Logs, metrics, traces - Dmytro Shapovalov (...
Teach your application eloquence. Logs, metrics, traces - Dmytro Shapovalov (...Teach your application eloquence. Logs, metrics, traces - Dmytro Shapovalov (...
Teach your application eloquence. Logs, metrics, traces - Dmytro Shapovalov (...
 
Best practices. Exploring - Ike Kurghinyan (RUS) | Ruby Meditation 26
Best practices. Exploring - Ike Kurghinyan (RUS) | Ruby Meditation 26Best practices. Exploring - Ike Kurghinyan (RUS) | Ruby Meditation 26
Best practices. Exploring - Ike Kurghinyan (RUS) | Ruby Meditation 26
 
Road to A/B testing - Alexey Vasiliev (ENG) | Ruby Meditation 25
Road to A/B testing - Alexey Vasiliev (ENG) | Ruby Meditation 25Road to A/B testing - Alexey Vasiliev (ENG) | Ruby Meditation 25
Road to A/B testing - Alexey Vasiliev (ENG) | Ruby Meditation 25
 
Concurrency in production. Real life example - Dmytro Herasymuk | Ruby Medita...
Concurrency in production. Real life example - Dmytro Herasymuk | Ruby Medita...Concurrency in production. Real life example - Dmytro Herasymuk | Ruby Medita...
Concurrency in production. Real life example - Dmytro Herasymuk | Ruby Medita...
 
Data encryption for Ruby web applications - Dmytro Shapovalov (RUS) | Ruby Me...
Data encryption for Ruby web applications - Dmytro Shapovalov (RUS) | Ruby Me...Data encryption for Ruby web applications - Dmytro Shapovalov (RUS) | Ruby Me...
Data encryption for Ruby web applications - Dmytro Shapovalov (RUS) | Ruby Me...
 
Rails App performance at the limit - Bogdan Gusiev
Rails App performance at the limit - Bogdan GusievRails App performance at the limit - Bogdan Gusiev
Rails App performance at the limit - Bogdan Gusiev
 
GDPR. Next Y2K in 2018? - Anton Tkachov | Ruby Meditation #23
GDPR. Next Y2K in 2018? - Anton Tkachov | Ruby Meditation #23GDPR. Next Y2K in 2018? - Anton Tkachov | Ruby Meditation #23
GDPR. Next Y2K in 2018? - Anton Tkachov | Ruby Meditation #23
 
Postgres vs Elasticsearch while enriching data - Vlad Somov | Ruby Meditaiton...
Postgres vs Elasticsearch while enriching data - Vlad Somov | Ruby Meditaiton...Postgres vs Elasticsearch while enriching data - Vlad Somov | Ruby Meditaiton...
Postgres vs Elasticsearch while enriching data - Vlad Somov | Ruby Meditaiton...
 

Recently uploaded

Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Enterprise Knowledge
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CVKhem
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUK Journal
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?Igalia
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsJoaquim Jorge
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?Antenna Manufacturer Coco
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 

Recently uploaded (20)

Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 

The Trailblazer Ride from the If Jungle into a Civilised Railway Station - Orban Botond (ENG) | Ruby Meditation 27

  • 1. From The If Jungle to A Civilised Railway Station By Botond Orban
  • 2. About Me Botond Orban Enthusiast IT Guy, Architect Enthusiastic about Ruby
 https://github.com/orbanbotond
 @orbanbotond
  • 3. The Origins The PC made in Ukraine
  • 4. Code can be written in a better way!
  • 5. Railway Oriented Development With 3 libraries in Parallel! -classic if jungle -dry transactions -monad do notation -trailblazer operations
  • 6. def create user = User.create user_params[:user] if user.valid? package = Package.create package_params[:user] if package.valid? user.package = package user.save SmsService.send_registration_msg(user, package) EmailService.send_registration_msg(user, package) SystemNotifierService.send_registration_msg(user, package) else render ... end else render ... end end True If Jungle Cyclomatic complexity: 2
  • 7. def create user = User.create user_params[:user] if user.valid? package = Package.create package_params[:user] if package.valid? package.user = user package.save if params[:coupon].present? if coupon = Coupon.exists? params[:coupon] discount = Discount.create params[:coupon] package.discount = discount package.save else render … end end SmsService.send_registration_msg(user, package) EmailService.send_registration_msg(user, package) SystemNotifierService.send_registration_msg(user, package) else render ... end else render ... end end True If Jungle Cyclomatic complexity: 4
  • 8. True If Jungle def create user = User.create user_params[:user] if user.valid? package = Package.create package_params[:user] if package.valid? package.user = user package.save if params[:coupon].present? if Coupon.exists? params[:coupon] discount = Discount.create params[:coupon] if discount.allowsUser? user package.discount = discount package.save else render ... end else render ... end end SmsService.send_registration_msg(user, package) EmailService.send_registration_msg(user, package) SystemNotifierService.send_registration_msg(user, package) else render ... end else render ... end end Cyclomatic complexity: 5
  • 11. If Jungle Implementation Specs: f(a,b) = a+b, a is infinite context 'add' do subject { add.call params: params } 
 context 'negative cases' do context 'params infinite' do let(:params) { [(1.0/0.0), 2] } specify 'Be a failure with a proper error message' do expect(subject[:validation]).to eq 'must be a real number' end end end
  • 12. add = ->(params:) do return { validation: 'must be a real number' } if params.any?{|x|x.infinite?} end Code: If Jungle Implementation f(a,b) = a+b, a is infinite
  • 13. Specs: context 'add' do subject { add.call params: params } let(:params) { [2,3,4] } context 'negative cases' do … context 'positive cases' do specify 'Be a success with the proper correct output' do expect(subject[:operation_result]).to eq(params.reduce(0) { |acc, x| acc + x }) end end end If Jungle Implementation f(a,b) = a+b,
  • 14. Code: add = ->(params:) do return { validation: 'must be a real number' } if params.any?{|x|x.infinite?} result = params.reduce(0) { |acc, x| acc + x } return { operation_result: result } end If Jungle Implementation f(a,b) = a+b,
  • 15. linear_function = ->(params:) do result = multiply.call(params: params[-2..-1]) if(result[:operation_result]) return add.call(params: [result[:operation_result], params[0]]) else return result end end rspec spec/railway_oriented_development/if_jungle_spec.rb ....... 7 examples, 0 failures If Jungle Implementation f(a,b,x) = a.x+b, Linear function
  • 16. Building Blocks Add Operation -Guard Condition -Business Logic: + Multiply Operation -Guard Condition -Business Logic: * LinearFunction -Delegation -Conditional -Delegation -Return a Result If Jungle Implementation
  • 18. Specs: context 'add' do subject { DryTransactions::Add.new.call params } 
 context 'negative cases' do context 'params infinite' do let(:params) { {params:[(1.0/0.0), 2]} } specify 'Be a failure with a proper error message' do expect(subject).to be_failure expect(subject.failure).to eq 'must be a real number' end end end Dry Transactions f(a,b) = a+b, a is infinite
  • 19. Code: module DryTransactions class Add include Dry::Transaction step :validate step :add private … … Dry Transactions f(a,b) = a+b, a is infinite
  • 21. Code: module DryTransactions class Add … private def validate(input) return Failure('must be a real number') unless input.all?{|x| x.finite?} Success(input) end
 def add(input) ret = input.reduce(0) { |acc, x| acc + x } Success(ret) end … Dry Transactions f(a,b) = a+b, a is infinite
  • 22. class LinearOperation include Dry::Transaction # a*x step :multiply # previous_result + b step :assembling_partial_results private … end Dry Transactions f(a, b, x) = a.x+b, Linear Function
  • 23. class ComplexOperation include Dry::Transaction … def multiply(input) partialValue = Multiply.new.call(params: [input[:params] [1], input[:params][2]]) partialValue.bind do |value| Success(input.merge(multiplication_result: partialValue.value!)) end end def assembling_partial_results(input) Add.new.call( params: [input[:params][0], input[:multiplication_result]]) end end rspec spec/railway_oriented_development/dry_transactions_spec.rb ....... 7 examples, 0 failures Dry Transactions f(a, b, x) = a.x+b, a is infinite
  • 24. Dry Transaction Implementation Add Operation -Guard Step -Business Logic Step: + Multiply Operation -Guard Step -Business Step: * LinearFunction -Multiply Step -Assemble Step Note: -no conditional compared to the If Jungle Solution! -linear execution by enlisting the steps!
  • 26. Specs: context 'add' do subject { MonadDoNotation::Add.new.call params } 
 context 'negative cases' do context 'params infinite' do let(:params) { [(1.0/0.0), 2] } specify 'Be a failure with a proper error message' do expect(subject).to be_failure expect(subject.failure[:validation]).to eq 'must be a real number' end end end Monad Do Notation f(a,b) = a+b, a is infinite
  • 27. Code: class Add include Dry::Monads::Result::Mixin include Dry::Monads::Do::All def call(arguments) validation_result = yield validate(arguments) operation_result = yield add(arguments) Success validation_result.merge( operation_result) end … end Monad Do Notation f(a,b) = a+b, a is infinite
  • 28. Code: class Add … def validate(input) return Failure(validation: 'must be a real number') unless input.all?{|x|x.finite?} Success(validation: :ok) end def add(input) ret = input.reduce(0) { |acc, x| acc + x } Success(operation_result: ret) end end … Monad Do Notation f(a,b) = a+b, a is infinite
  • 29. class LinearOperation include Dry::Monads::Result::Mixin include Dry::Monads::Do::All def call(input) multiplication = yield multiply(input[-2..-1]) addition = yield add([input[0], multiplication[:operation_result]]) Success(addition) end private … Monad Do Notation f(a, b, x) = a.x+b,
  • 30. class LinearOperation include Dry::Monads::Result::Mixin include Dry::Monads::Do::All … private def multiply(args) Multiply.new.call args end def add(args) Add.new.call args end end rspec spec/railway_oriented_development/monad_do_notation_spec.rb ....... 7 examples, 0 failures Monad Do Notation f(a, b, x) = a.x+b,
  • 31. Add Operation -Validate Method -Business Logic Method: + Multiply Operation -Validate Method -Business Logic Method: * LinearFunction -Multiply Method -Add Method Step Note: -no conditional compared to the If Jungle Solution! -linear execution! -pure Ruby! ***** Monad Do Notation Implementation
  • 33. Specs: context 'add' do subject { TrailblazerOperations::Add.call params: params } 
 context 'negative cases' do context 'params infinite' do let(:params) { [(1.0/0.0), 2] } specify 'Be a failure with a proper error message' do expect(subject).to be_failure expect(subject[:validation]).to eq 'must be a real number' end end end Trailblazer Operations f(a,b) = a+b, a is infinite
  • 34. Code: module TrailblazerOperations class Add < Trailblazer::Operation step :validate step :add private … end End Trailblazer Operations f(a,b) = a+b, a is infinite
  • 36. Code: module TrailblazerOperations class Add < Trailblazer::Operation … private def validate(options, params:) unless params.all?{|x|x.finite?} options[:validation] = 'must be a real number' return Railway.fail! end Railway.pass! end def add(options, params:, **rest) ret = params.reduce(0) { |acc, x| acc + x } options[:operation_result] = ret end end end end
  • 37. Code: class LinearOperation < Trailblazer::Operation step Nested( Multiply, input: -> (options, params:, **) do options.merge params: params[-2..-1] end ) step Nested( Add, input: -> (options, params:, **) do options.to_hash.except(:operation_result).merge params: [params[0], options[:operation_result]] end ) end rspec spec/railway_oriented_development/trailblazer_operations_spec.rb ....... 7 examples, 0 failures Trailblazer Operations f(a, b, x) = a.x+b,
  • 38. Add Operation -Validate Step -Business Logic Step: + Multiply Operation -Validate Step -Business Logic Step: * LinearFunction -Delegates to the Multiply Operation by Nesting -Delegates to the Add Operation by Nesting Note: -no conditional compared to the If Jungle Solution! -linear execution! -DSL for reuse! Trailblazer Implementation
  • 39. Dry-Transaction Monad Do Notation Trailblazer Steps Steps Ruby Code Wrapped With Yield Steps Code Reuse Ruby Call Ruby Code Wrapped With Yield DSL for other Operation Reuse!
  • 40. True If Jungle def create user = User.create user_params[:user] if user.valid? package = Package.create package_params[:user] if package.valid? package.user = user package.save if params[:coupon].present? if Coupon.exists? params[:coupon] discount = Discount.create params[:coupon] if discount.allowsUser? user package.discount = discount package.save else render ... end else render ... end end SmsService.send_registration_msg(user, package) EmailService.send_registration_msg(user, package) SystemNotifierService.send_registration_msg(user, package) else render ... end else render ... end end Cyclomatic complexity: 5
  • 41. Railway Oriented Development Cyclomatic complexity: 1-2 class Add < Trailblazer::Operation step :persist_user step :persist_package step :add_coupon_based_discount step :notify_about_registration ... end
  • 42. Railway Oriented Development Cyclomatic complexity: 1-2 class Add < Trailblazer::Operation step :persist_user failure :log_user_persistance step :persist_package failure :log_package_persistance step :add_coupon_based_discount failure :log_discount_creation step :notify_about_registration ... end
  • 43. Railway Oriented Development Cyclomatic complexity: 1-2 class Add < Trailblazer::Operation step :persist_user failure :log_user_persistance step :persist_package failure :log_package_persistance step :add_coupon_based_discount failure :log_discount_creation step :notify_about_registration step :notify_facebook_friends … end
  • 44. Contract for every input (entity & other use case)
 
 Basement:
 -Operations for CRUD 
 Crud (and Other) Reuse (DRY): -Operations for Onboarding -Operations for Admin -Operations for handling Business Use Cases Trailblazer Operations & Contracts (Reform) My Best Practice
  • 45.
  • 46.
  • 47.
  • 48.
  • 49. Thank you ;) Botond Orban Enthusiast IT Guy, Architect Enthusiastic about Ruby
 https://github.com/orbanbotond
 @orbanbotond