Transcript
Page 1: [Practical] Functional Programming in Rails

FUNCTIONALPROGRAMMINGPr

actical!

RAILSRUBYIN

ON

BY

Page 2: [Practical] Functional Programming in Rails

Overview

• What is a Service Layer? • Railway Oriented Programming • Creating Beautifully Composable Services

Page 3: [Practical] Functional Programming in Rails

What is a

LAYER?

SERVICE

Page 4: [Practical] Functional Programming in Rails

What is a

LAYER

SERVICE??

Page 5: [Practical] Functional Programming in Rails

A Service is an object that represents a process.

Page 6: [Practical] Functional Programming in Rails

A process is something you do.

• Typically initiated by the user • Usually implemented as a dedicated class • Named with verbs, not nouns • Examples: SignupUser, PurchaseItem, etc.

SERVICES

Page 7: [Practical] Functional Programming in Rails

SignupUser

Purchase Item

RAILS

SERVICES

SERVICE LAYER

Payout Account

Page 8: [Practical] Functional Programming in Rails

A Service in Rails

SERVICES

CODE EXAMPLE

A ServiceUsage in Controller

Page 9: [Practical] Functional Programming in Rails

[Naive] ValidationsCODE EXAMPLE

A Service

Usage in Controller

SERVICES

Page 10: [Practical] Functional Programming in Rails

Why a Service useful?

• It encapsulates domain logic • It thins out your models & controllers • It ties together cross-cutting concerns • It makes your Rails app easier to test.

SERVICES

Page 11: [Practical] Functional Programming in Rails

A service layer is about clear separation.

• Rails depends on the service layer • The service layer knows nothing about Rails (routes, controllers, & views)

• Other things could depend on the service layer (REST API, web sockets, rake tasks, etc.)

• ActiveRecord is unavoidable, however.SERVICES

Page 12: [Practical] Functional Programming in Rails

SERVICES

Page 13: [Practical] Functional Programming in Rails

Quick Recap

• A service is an object that represents a process • Services encapsulate domain logic for specific

processes • No functional programming (yet).

SERVICES

Page 14: [Practical] Functional Programming in Rails

RAILWAY ORIENTED

PROGRAMMING

http://fsharpforfunandprofit.com/posts/recipe-part2/

Page 15: [Practical] Functional Programming in Rails

Services: Another Perspective

A service is a sequence of steps • They often involve a lot of setup • Authentication, authorization, validation, etc.

Any one of these steps could fail • How to handle failure??

RAILWAY

Page 16: [Practical] Functional Programming in Rails

Naive ValidationsCODE EXAMPLE (REVISITED)

A Service RAILWAY

Page 17: [Practical] Functional Programming in Rails

Can we do be!er?

RAILWAY

What if each step was an independent method?

How would each step communicate?

Page 18: [Practical] Functional Programming in Rails

Source: http://www.slideshare.net/ScottWlaschin/railway-oriented-programming RAILWAY

The “Switch”

Input → Success!

Failure.

fetch_item

DIAGRAM

Page 19: [Practical] Functional Programming in Rails

RAILWAY

The “Switch”

Input → Success!

Failure

fetch_item

CODE EXAMPLE

Page 20: [Practical] Functional Programming in Rails

RAILWAY

The “Switch”

Input → Success!

Failure.

fetch_item

CODE EXAMPLE

Failure.Success!

Page 21: [Practical] Functional Programming in Rails

Source: http://www.slideshare.net/ScottWlaschin/railway-oriented-programming RAILWAY

Our Target Flow

on successSuccess!

Failure.

Input →

fetch_item validate

on failure

Page 22: [Practical] Functional Programming in Rails

Source: http://www.slideshare.net/ScottWlaschin/railway-oriented-programming RAILWAY

Our Target Flow

Success!Failure.

Input →create_ordervalidatefetch_item

Page 23: [Practical] Functional Programming in Rails

Source: http://www.slideshare.net/ScottWlaschin/railway-oriented-programming RAILWAY

Our Target Flow

Success!Failure.

Input →create_ordervalidatefetch_item

IT’D BE COOL IF WE COULD CONNECT THESE TOGETHER

Page 24: [Practical] Functional Programming in Rails

Source: http://www.slideshare.net/ScottWlaschin/railway-oriented-programming RAILWAY

Connecting Switches

Success!Failure.

Input →create_ordervalidatefetch_item

create_ordervalidatefetch_item

Page 25: [Practical] Functional Programming in Rails

Source: http://www.slideshare.net/ScottWlaschin/railway-oriented-programming RAILWAY

Connecting Switches

Success!Failure.

Input →create_ordervalidatefetch_item

create_ordervalidatefetch_item

create_ordervalidatefetch_item

Success!Failure.

Page 26: [Practical] Functional Programming in Rails

RAILWAY

Connecting SwitchesCODE EXAMPLES

create_ordervalidatefetch_item

?? ??

Page 27: [Practical] Functional Programming in Rails

RAILWAY

Connecting SwitchesCODE EXAMPLES

create_ordervalidatefetch_item

?? ??

HOW DO WE CONNECTIT ALL TOGETHER?

? ????

??

?

Page 28: [Practical] Functional Programming in Rails

RAILWAY

Answer:

Page 29: [Practical] Functional Programming in Rails

RAILWAY

¯\_(ツ)_/¯ Answer:

Page 30: [Practical] Functional Programming in Rails

RAILWAY

¯\_(ツ)_/¯ Answer:

IT DOESN’T MATTER!

Page 31: [Practical] Functional Programming in Rails

RAILWAY

¯\_(ツ)_/¯ Answer:

IT DOESN’T MATTER! :D

Page 32: [Practical] Functional Programming in Rails

RAILWAY

¯\_(ツ)_/¯ Answer:

IT DOESN’T MATTER! :D

(actual answer: monads)

Page 33: [Practical] Functional Programming in Rails

There’s a gem for that!Doesn’t matter.

RAILWAY

github.com/mindeavor/solid_use_case

Page 34: [Practical] Functional Programming in Rails

There’s a gem for that!Don’t worry.

Page 35: [Practical] Functional Programming in Rails

Handling failures?

RAILWAY

What about

github.com/mindeavor/solid_use_case

Page 36: [Practical] Functional Programming in Rails
Page 37: [Practical] Functional Programming in Rails

Quick Recap

• Split steps into methods • Return a success or failure in each one • Elegant (with gem) error handling! • Steps can be tested independently

RAILWAY

Page 38: [Practical] Functional Programming in Rails

COMPOSING SERVICES

FOR MAXIMUM COOLNESS

Page 39: [Practical] Functional Programming in Rails

Source: http://www.slideshare.net/ScottWlaschin/railway-oriented-programming COMPOSE

Remember This?

Success!Failure

Input →create_ordervalidatefetch_item

create_ordervalidatefetch_item

create_ordervalidatefetch_item

Success!Failure

Page 40: [Practical] Functional Programming in Rails

Source: http://www.slideshare.net/ScottWlaschin/railway-oriented-programming COMPOSE

Input → Success!Failure

create_ordervalidatefetch_item

What if we treat it like a single thing…

Page 41: [Practical] Functional Programming in Rails

Source: http://www.slideshare.net/ScottWlaschin/railway-oriented-programming COMPOSE

Input → Success!FailurePurchaseItem

What if we treat it like a single thing…

Page 42: [Practical] Functional Programming in Rails

Source: http://www.slideshare.net/ScottWlaschin/railway-oriented-programming COMPOSE

Input → PurchaseItem Success!Failure

What if we treat it like a single thing…

Page 43: [Practical] Functional Programming in Rails

Source: http://www.slideshare.net/ScottWlaschin/railway-oriented-programming COMPOSE

…and then connect it to other things??

Input →PurchaseItem

Success!

Failure

Page 44: [Practical] Functional Programming in Rails

Source: http://www.slideshare.net/ScottWlaschin/railway-oriented-programming COMPOSE

Input →PurchaseItem EmailReceipt

Success!

Failure

…and then connect it to other things??

Page 45: [Practical] Functional Programming in Rails

Service CompositionCODE EXAMPLE

COMPOSE

Page 46: [Practical] Functional Programming in Rails

Service CompositionCODE EXAMPLE

Another Service!

COMPOSE

Page 47: [Practical] Functional Programming in Rails

Service CompositionCODE EXAMPLE

Another Service!

COMPOSE

Page 48: [Practical] Functional Programming in Rails

Recap

• We can compose services like we can steps (in fact we can compose anything that returns our success or failure)

• Functional programming rocks!

COMPOSE

Page 49: [Practical] Functional Programming in Rails

Conclusion

• Service layers are great for apps more complex than CRUD

• Railway oriented programming is great for seamless error handling

• Functional programming gives us composable services!

Page 50: [Practical] Functional Programming in Rails

In the end, don’t take my word for it.

Page 51: [Practical] Functional Programming in Rails

TRY IT YOURSELF!

Page 52: [Practical] Functional Programming in Rails

Thanks!Hurrah!

END.THE

BY

- Gilbert (@mindeavor)

Page 53: [Practical] Functional Programming in Rails

Further Reading

• http://martinfowler.com/eaaCatalog/serviceLayer.html • https://gist.github.com/blaix/5764401 • http://fsharpforfunandprofit.com/posts/recipe-part2/ • The gem: https://github.com/mindeavor/solid_use_case


Top Related