SlideShare a Scribd company logo
SAY GOODBYE TO
PROCEDURAL*
PROGRAMMING
ANOTHER USELESS PRESENTATION
BROUGHT TO YOU BY @APOTONICK
SAY GOODBYE TO
PROCEDURAL*
PROGRAMMING
* AS WE KNOW IT.
<wrong>
REVEAL.JS
AND HOW TO MASTER IT, PART I OF VIII
[ ] DIAGRAMS
[ ] 6 MEMES
[ ] 2 BULLET POINT LISTS
[ ] QUOTE FROM SOMEONE
[ ] MORE DIAGRAMS
[ ] TRUCKLOADS OF CODE (you wanted it)
[ ] DIAGRAMS
[ ] 6 MEMES
[x ] 2 BULLET POINT LISTS
[ ] QUOTE FROM SOMEONE
[ ] MORE DIAGRAMS
[ ] TRUCKLOADS OF CODE (you wanted it)
class Post < ActiveRecord::Base
validates :body, presence:true
validates :author, presence:true
after_save :notify_moderators!, if: :create?
end
 
class PostsController < ApplicationController
def create
return unless can?(current_user, Post, :new)
post = Post.new(author: current_user)
if post.update_attributes(
params.require(:post).permit(:title)
)
post.save
notify_current_user!
else
render :new
end
end
end
Let's not talk
about persistence!
Let's not talk
about business logic!
Let's not talk
about views!
I SAID: RAILS VIEWS!
Notes:
let's come back to the problems in our example it's
hard to understand what we are trying to do and:
HOW DO I
TEST THAT?
class Post < ActiveRecord::Base
validates :body, presence:true
validates :author, presence:true
after_save :notify_moderators!, if: :create?
end
describe Post do
it "validates and notifies moderators" do
post = Post.create( valid_params )
expect(post).to be_persisted
end
end
class Post < ActiveRecord::Base
validates :body, presence:true
validates :author, presence:true
after_save :notify_moderators!, if: :create?
end
describe Post do
it "validates and notifies moderators" do
post = Post.create( valid_params )
expect(post).to be_persisted
end
end
it do
controller = Controller.new
controller.create( valid_params )
expect(Post.last).to be_persisted
end
describe BlogPostsController do
it "creates BlogPost model" do
post :create, blog_post: valid_params
expect(response).to be_ok
expect(BlogPost.last).to be_persisted
end
end
...THINKING...
...THINKING...
[...] It extends the basic MVC pattern
with new abstractions.
NO!
class MyService
def self.call(args)
# do something here
end
end
MyService.( valid_params )
Notes: we don't need any domain logic, that's very
user specific and shouldn't be dictated by "my
framework"
class MyService
def call(params)
return unless can?(current_user, Post, :new)
post = Post.new(author: current_user)
post.update_attributes(
params.require(:post).permit(:title)
)
if post.save
notify_current_user!
end
end
end
[ ] DIAGRAMS
[x] 6 MEMES
[x ] 2 BULLET POINT LISTS
[ ] QUOTE FROM SOMEONE
[ ] MORE DIAGRAMS
[ ] TRUCKLOADS OF CODE (you wanted it)
class MyService
def call(params)
return unless can?(current_user, Post, :new)
post = Post.new(author: current_user)
post.update_attributes(
params.require(:post).permit(:title)
)
if post.save
notify_current_user!
end
end
end
TEST
it do
service = MyService.new
service.call( valid_params )
expect(Post.last).to be_persisted
end
HAPPY!
...THINKING...
SERVICE OBJECTS, REVISITED
[x] Encapsulation
[x] Testing
[ ] What to return?
[ ] Validations extracted?
[ ] Extendable
class MyService
def call(params)
end
end
Is the problem the
procedural* code design?
AND THAT'S TRB.
THANK YOU!
QUESTIONS?
OK, I GOT
A QUESTION
THEN:
DO YOU WANT
SOME CODE?
DO YOU WANT
SOME CODE?
NO?
class Create < Trailblazer::Operation
#
#
#
end
class BlogPost::Create < Trailblazer::Operation
#
#
#
end
class Create < Trailblazer::Operation
#
#
#
end
class Create < Trailblazer::Operation
def process(params)
# sam's code here
end
end
Notes: not really extendable
class Create < Trailblazer::Operation
def process(params)
return unless can?(current_user, Post, :new)
post = Post.new(author: current_user)
post.update_attributes(
params.require(:post).permit(:title)
)
if post.save
notify_current_user!
end
end
end
class Create < Trailblazer::Operation
#
#
#
end
result = Create.()
result.success? #=> true
Notes:
Hooray, we have an API for service objects!
HOORAY, A
SERVICE
OBJECT
API!
class Create < Trailblazer::Operation
#
#
#
#
end
class Create < Trailblazer::Operation
step :create_model!
step :validate!
step :save!
step :notify_current_user!
end
class Create < Trailblazer::Operation
step :create_model!
step :validate!
step :save!
step :notify_current_user!
end
class Create < Trailblazer::Operation
step :create_model!
#
#
#
#
end
class Create < Trailblazer::Operation
step :create_model!
def create_model!(options, **)
end
end
CREATE MODEL
class Create < Trailblazer::Operation
step :create_model!
def create_model!(options, **)
options["model"] = BlogPost.new
end
end
result = Create.()
result.success? #=> true
result["model"] #=> #<BlogPost id:nil, ..>
VALIDATE
class Create < Trailblazer::Operation
step :create_model!
step :validate!
def create_model!(options, **)
# ..
def validate!(options, params:, **)
# validate params
end
end
valid_params = { body: "Blogging's fun. #not" }
Create.( valid_params )
class Create < Trailblazer::Operation
# ..
def validate!(options, params:, **)
params #=> { body: "Blogging's fun. #not" }
end
end
Notes: sending params into the op
class Create < Trailblazer::Operation
# ..
def validate!(options, params:, **)
model = options["model"] # from the create_model! step...
if model.update_attributes(params)
true
else
false
end
end
end
class Create < Trailblazer::Operation
# ..
def validate!(options, params:, model:, **)
#
#
if model.update_attributes(params)
true
else
false
end
end
end
#class Create < Trailblazer::Operation
# ..
def validate!(options, params:, model:, **)
if model.update_attributes(params)
true
else
false
end
end
#end
#class Create < Trailblazer::Operation
# ..
def validate!(options, params:, model:, **)
#
#
#
#
model.update_attributes(params)
end
#end
class Create < Trailblazer::Operation
step :create_model!
step :validate!
step :save!
#
#
#
#
#
#
end
class Create < Trailblazer::Operation
step :create_model!
step :validate!
step :save!
#def create_model!(options, **)
#def validate!(options, params:, **)
def save!(options, params:, model:, **)
true
end
end
class Create < Trailblazer::Operation
step :create_model!
step :validate!
step :save!
step :notify!
#def create_model!(options, **)
#def validate!(options, params:, **)
#def save!(options, params:, model:, **)
def notify!(options, model:, **)
MyMailer.call(model)
end
end
HAPPY
TIMES!
... AND WHEN
THINGS
GO WRONG?
class Create < Trailblazer::Operation
step :create_model!
step :validate!
step :save!
step :notify!
#def create_model!(options, **)
#def validate!(options, params:, **)
#def save!(options, params:, model:, **)
#def notify!(options, model:, **)
end
class Create < Trailblazer::Operation
step :create_model!
step :validate! [XXX]
step :save!
step :notify!
#def create_model!(options, **)
#def validate!(options, params:, **)
#def save!(options, params:, model:, **)
#def notify!(options, model:, **)
end
#class Create < Trailblazer::Operation
# ..
def validate!(options, params:, model:, **)
model.update_attributes(params) #=> false
end
#end
class Create < Trailblazer::Operation
step :create_model!
step :validate!
step :save!
step :notify!
failure :handle!
#..
end
class Create < Trailblazer::Operation
step :create_model!
step :validate!
step :save!
step :notify!
failure :handle!
#..
def handle!(options, **)
options["error"] = "don't cry!"
end
end
result = Create.( { title: nil } )
result.success? #=> false
result["error"] = "don't cry!"
RAILWAYS
ROCK!
BUT ISN'T THAT
SUPER
COMPLEX?
DUDE.
Notes: do you find this more complex than this?
class MyService
def call(params)
return unless can?(current_user, Post, :new)
post = Post.new(author: current_user)
if post.update_attributes(
params.require(:post).permit(:title)
)
unless notify_current_user!
if ...
else
end
end
end
class Create < Trailblazer::Operation
step :create_model!
step :validate!
step :save!
step :notify!
failure :handle!
# ..
end
def create_model!(options, **)
def validate!( options, params:, **)
def save!( options, params:, model:, **)
def notify!( options, model:, **)
result = Create.( { title: nil } )
result.success? #=> false
result["error"] #=> "don't cry!"
result["model"] #=> #<BlogPost title: nil>
TEST
it "fails with empty title" do
result = Create.( { title: nil } )
expect(result).to be_success
expect(result["error"]).to eq("don't cry!")
expect(result["model"]).to be_persisted
end
rspec-trailblazer
minitest-trailblazer
Notes:
validations still in model
class PostsController < ApplicationController
def create
return unless can?(current_user, Post, :new)
post = Post.new(author: current_user)
if post.update_attributes(
params.require(:post).permit(:title))
notify_current_user!
else
render :new
end
end
end
class PostsController < ApplicationController
def create
return unless can?(current_user, Post, :new)
#
#
#
result = BlogPost::Create.( params )
if result.failure?
render :new
end
end
end
AUTHORIZATION
def create
return unless can?(current_user, Post, :new)
# ..
class Create < Trailblazer::Operation
step :authorize!
#step :create_model!
#step :validate!
#step :save!
#step :notify!
#failure :handle!
# ..
end
class Create < Trailblazer::Operation
step :authorize!
# ..
def authorize!(options, current_user:, **)
CouldCould.can?(current_user, Post, :new)
end
end
CURRENT WHAT?
def authorize!(options, current_user:, **)
CouldCould.can?(
current_user, # wtf?
Post, :new
)
end
class PostsController < ApplicationController
def create
return unless can?(current_user, Post, :new)
result = BlogPost::Create.( params )
#
#
#
if result.failure?
render :new
end
end
end
class PostsController < ApplicationController
def create
return unless can?(current_user, Post, :new)
result = BlogPost::Create.(
params,
"current_user" => current_user
)
if result.failure?
render :new
end
end
end
class PostsController < ApplicationController
def create
#return unless can?(current_user, Post, :new)
#
result = BlogPost::Create.(
params,
"current_user" => current_user
)
if result.failure?
render :new
end
end
end
class PostsController < ApplicationController
def create
result = BlogPost::Create.(
params,
"current_user" => current_user
)
if result.failure?
render :new
end
end
end
class PostsController < ApplicationController
def create
run BlogPost::Create, "current_user" => current_user do
return
end
render :new
end
end
class PostsController < ApplicationController
def create
run BlogPost::Create do
return
end
render :new
end
end
class PostsController < ApplicationController
def create
run BlogPost::Create do |result|
return redirect_to blog_post_path(result["model"].id)
end
render :new
end
end
class PostsController < ApplicationController
def create
run BlogPost::Create do |result|
return redirect_to blog_post_path(result["model"
end
render :new
end
end
DEPENDENCY INJECTION
it "works with current_user" do
result = Create.(
valid_params,
"current_user" => User.find(1) )
# ..
end
class Create < Trailblazer::Operation
step :authorize!
# ..
def authorize!(options, current_user:, **)
CouldCould.can?(current_user, Post, :new)
end
end
class Create < Trailblazer::Operation
step MyAuth
# ..
class MyAuth
def self.call(options, current_user:, **)
CouldCould.can?(current_user, Post, :new)
end
end
end
class Create < Trailblazer::Operation
step MyAuthCallableSittingSomewhere
# ..
#class MyAuth
# def self.call(options, current_user:, **)
# CouldCould.can?(current_user, Post, :new)
# end
#end
end
DYI SUCKS
class Create < Trailblazer::Operation
step Policy::CanCan( Post, :new )
# step :model!
# ..
end
VALIDATIONS:
A STORY OF MANKIND
class Post < ActiveRecord::Base
validates :title, presence:true
validates :body, presence:true
#after_save :notify_moderators!, if: :create?
end
module BlogPost
module Contract
class Create::Create < Reform::Form
property :title
property :body
validates :title, presence:true
validates :body, presence:true
end
end
end
class Create < Trailblazer::Operation
step Policy::CanCan( Post, :new )
step :model!
step :validate!
step :notify!
# ..
def model!(options, **)
def validate!(options, **)
# ..
end
class Create < Trailblazer::Operation
step Policy::CanCan( Post, :new )
step :model!
step Contract::Build( constant: Contract::Create )
step Contract::Validate()
step Contract::Persist()
step :notify!
# ..
def model!(options, **)
# ..
end
BPMN
class Create < Trailblazer::Operation
step :create_model!
step :validate!
step :save!
step :notify!
failure :handle!
# ..
end
result = Create.(
params,
"current_user" => ..
)
SAY GOODBYE TO
PROCEDURAL*
PROGRAMMING
* AS WE KNOW IT.
Trailblazer is awesome!
             -- Someone
[ ] DIAGRAMS
[x] 6 MEMES
[xX] 2 BULLET POINT LISTS
[x] QUOTE FROM SOMEONE
[x] MORE DIAGRAMS
[ ] TRUCKLOADS OF CODE (you wanted it)
@APOTONICK
❤

More Related Content

What's hot

Workshop 26: React Native - The Native Side
Workshop 26: React Native - The Native SideWorkshop 26: React Native - The Native Side
Workshop 26: React Native - The Native Side
Visual Engineering
 
Synapseindia reviews sharing intro cakephp
Synapseindia reviews sharing intro cakephpSynapseindia reviews sharing intro cakephp
Synapseindia reviews sharing intro cakephp
SynapseindiaComplaints
 
Django tricks (2)
Django tricks (2)Django tricks (2)
Django tricks (2)
Carlos Hernando
 
Practical Protocol-Oriented-Programming
Practical Protocol-Oriented-ProgrammingPractical Protocol-Oriented-Programming
Practical Protocol-Oriented-Programming
Natasha Murashev
 
Two Scoops of Django - Common Patterns for Forms
Two Scoops of Django - Common Patterns for FormsTwo Scoops of Django - Common Patterns for Forms
Two Scoops of Django - Common Patterns for Forms
Vic Yang
 
Real life-coffeescript
Real life-coffeescriptReal life-coffeescript
Real life-coffeescript
David Furber
 
Workshop 23: ReactJS, React & Redux testing
Workshop 23: ReactJS, React & Redux testingWorkshop 23: ReactJS, React & Redux testing
Workshop 23: ReactJS, React & Redux testing
Visual Engineering
 
Ember - introduction
Ember - introductionEmber - introduction
Ember - introduction
Harikrishnan C
 
Solid angular
Solid angularSolid angular
Solid angular
Nir Kaufman
 
Working Effectively With Legacy Code
Working Effectively With Legacy CodeWorking Effectively With Legacy Code
Working Effectively With Legacy Code
scidept
 
Complex Architectures in Ember
Complex Architectures in EmberComplex Architectures in Ember
Complex Architectures in Ember
Matthew Beale
 
Sylius and Api Platform The story of integration
Sylius and Api Platform The story of integrationSylius and Api Platform The story of integration
Sylius and Api Platform The story of integration
Łukasz Chruściel
 
Workshop 19: ReactJS Introduction
Workshop 19: ReactJS IntroductionWorkshop 19: ReactJS Introduction
Workshop 19: ReactJS Introduction
Visual Engineering
 
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)arcware
 
2013 - Nate Abele: HTTP ALL THE THINGS: Simplificando aplicaciones respetando...
2013 - Nate Abele: HTTP ALL THE THINGS: Simplificando aplicaciones respetando...2013 - Nate Abele: HTTP ALL THE THINGS: Simplificando aplicaciones respetando...
2013 - Nate Abele: HTTP ALL THE THINGS: Simplificando aplicaciones respetando...
PHP Conference Argentina
 
Vuejs testing
Vuejs testingVuejs testing
Vuejs testing
Greg TAPPERO
 
Introduction To Angular's reactive forms
Introduction To Angular's reactive formsIntroduction To Angular's reactive forms
Introduction To Angular's reactive forms
Nir Kaufman
 
Cucumber
CucumberCucumber
Cucumber
markjturner
 
MidCamp 2016 - Demystifying AJAX Callback Commands in Drupal 8
MidCamp 2016 - Demystifying AJAX Callback Commands in Drupal 8MidCamp 2016 - Demystifying AJAX Callback Commands in Drupal 8
MidCamp 2016 - Demystifying AJAX Callback Commands in Drupal 8
Michael Miles
 
Swift Delhi: Practical POP
Swift Delhi: Practical POPSwift Delhi: Practical POP
Swift Delhi: Practical POP
Natasha Murashev
 

What's hot (20)

Workshop 26: React Native - The Native Side
Workshop 26: React Native - The Native SideWorkshop 26: React Native - The Native Side
Workshop 26: React Native - The Native Side
 
Synapseindia reviews sharing intro cakephp
Synapseindia reviews sharing intro cakephpSynapseindia reviews sharing intro cakephp
Synapseindia reviews sharing intro cakephp
 
Django tricks (2)
Django tricks (2)Django tricks (2)
Django tricks (2)
 
Practical Protocol-Oriented-Programming
Practical Protocol-Oriented-ProgrammingPractical Protocol-Oriented-Programming
Practical Protocol-Oriented-Programming
 
Two Scoops of Django - Common Patterns for Forms
Two Scoops of Django - Common Patterns for FormsTwo Scoops of Django - Common Patterns for Forms
Two Scoops of Django - Common Patterns for Forms
 
Real life-coffeescript
Real life-coffeescriptReal life-coffeescript
Real life-coffeescript
 
Workshop 23: ReactJS, React & Redux testing
Workshop 23: ReactJS, React & Redux testingWorkshop 23: ReactJS, React & Redux testing
Workshop 23: ReactJS, React & Redux testing
 
Ember - introduction
Ember - introductionEmber - introduction
Ember - introduction
 
Solid angular
Solid angularSolid angular
Solid angular
 
Working Effectively With Legacy Code
Working Effectively With Legacy CodeWorking Effectively With Legacy Code
Working Effectively With Legacy Code
 
Complex Architectures in Ember
Complex Architectures in EmberComplex Architectures in Ember
Complex Architectures in Ember
 
Sylius and Api Platform The story of integration
Sylius and Api Platform The story of integrationSylius and Api Platform The story of integration
Sylius and Api Platform The story of integration
 
Workshop 19: ReactJS Introduction
Workshop 19: ReactJS IntroductionWorkshop 19: ReactJS Introduction
Workshop 19: ReactJS Introduction
 
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
 
2013 - Nate Abele: HTTP ALL THE THINGS: Simplificando aplicaciones respetando...
2013 - Nate Abele: HTTP ALL THE THINGS: Simplificando aplicaciones respetando...2013 - Nate Abele: HTTP ALL THE THINGS: Simplificando aplicaciones respetando...
2013 - Nate Abele: HTTP ALL THE THINGS: Simplificando aplicaciones respetando...
 
Vuejs testing
Vuejs testingVuejs testing
Vuejs testing
 
Introduction To Angular's reactive forms
Introduction To Angular's reactive formsIntroduction To Angular's reactive forms
Introduction To Angular's reactive forms
 
Cucumber
CucumberCucumber
Cucumber
 
MidCamp 2016 - Demystifying AJAX Callback Commands in Drupal 8
MidCamp 2016 - Demystifying AJAX Callback Commands in Drupal 8MidCamp 2016 - Demystifying AJAX Callback Commands in Drupal 8
MidCamp 2016 - Demystifying AJAX Callback Commands in Drupal 8
 
Swift Delhi: Practical POP
Swift Delhi: Practical POPSwift Delhi: Practical POP
Swift Delhi: Practical POP
 

Viewers also liked

Collage days
Collage daysCollage days
Collage days
ripal_queenruler
 
Rodauth: Clean Authentication - Valentine Ostakh
Rodauth: Clean Authentication - Valentine OstakhRodauth: Clean Authentication - Valentine Ostakh
Rodauth: Clean Authentication - Valentine Ostakh
Ruby Meditation
 
Ruby Gems and Native Extensions - Stas Volovyk
Ruby Gems and Native Extensions - Stas VolovykRuby Gems and Native Extensions - Stas Volovyk
Ruby Gems and Native Extensions - Stas Volovyk
Ruby Meditation
 
Funtional Ruby - Mikhail Bortnyk
Funtional Ruby - Mikhail BortnykFuntional Ruby - Mikhail Bortnyk
Funtional Ruby - Mikhail Bortnyk
Ruby Meditation
 
Evident Secrets of Successful Application - Max Goncharov
Evident Secrets of Successful Application - Max GoncharovEvident Secrets of Successful Application - Max Goncharov
Evident Secrets of Successful Application - Max Goncharov
Ruby Meditation
 
Functional Web Apps with WebMachine Framework - Mikhail Bortnyk
Functional Web Apps with WebMachine Framework - Mikhail BortnykFunctional Web Apps with WebMachine Framework - Mikhail Bortnyk
Functional Web Apps with WebMachine Framework - Mikhail Bortnyk
Ruby Meditation
 
Lets build a game (in 24 min) by Ivan Zarea
Lets build a game (in 24 min) by Ivan ZareaLets build a game (in 24 min) by Ivan Zarea
Lets build a game (in 24 min) by Ivan Zarea
Pivorak MeetUp
 
A Farewell Letter_ Gabriel Garcia Marquez
A Farewell Letter_ Gabriel Garcia MarquezA Farewell Letter_ Gabriel Garcia Marquez
A Farewell Letter_ Gabriel Garcia Marquez
Vili 48
 
Funny retirement slides
Funny retirement slidesFunny retirement slides
Funny retirement slides
Patti Poe
 
FAREWELL
FAREWELLFAREWELL
FAREWELL
OH TEIK BIN
 

Viewers also liked (12)

Collage days
Collage daysCollage days
Collage days
 
Rodauth: Clean Authentication - Valentine Ostakh
Rodauth: Clean Authentication - Valentine OstakhRodauth: Clean Authentication - Valentine Ostakh
Rodauth: Clean Authentication - Valentine Ostakh
 
Ruby Gems and Native Extensions - Stas Volovyk
Ruby Gems and Native Extensions - Stas VolovykRuby Gems and Native Extensions - Stas Volovyk
Ruby Gems and Native Extensions - Stas Volovyk
 
Funtional Ruby - Mikhail Bortnyk
Funtional Ruby - Mikhail BortnykFuntional Ruby - Mikhail Bortnyk
Funtional Ruby - Mikhail Bortnyk
 
Evident Secrets of Successful Application - Max Goncharov
Evident Secrets of Successful Application - Max GoncharovEvident Secrets of Successful Application - Max Goncharov
Evident Secrets of Successful Application - Max Goncharov
 
Functional Web Apps with WebMachine Framework - Mikhail Bortnyk
Functional Web Apps with WebMachine Framework - Mikhail BortnykFunctional Web Apps with WebMachine Framework - Mikhail Bortnyk
Functional Web Apps with WebMachine Framework - Mikhail Bortnyk
 
Lets build a game (in 24 min) by Ivan Zarea
Lets build a game (in 24 min) by Ivan ZareaLets build a game (in 24 min) by Ivan Zarea
Lets build a game (in 24 min) by Ivan Zarea
 
A Farewell Letter_ Gabriel Garcia Marquez
A Farewell Letter_ Gabriel Garcia MarquezA Farewell Letter_ Gabriel Garcia Marquez
A Farewell Letter_ Gabriel Garcia Marquez
 
Farewell quiz
Farewell quizFarewell quiz
Farewell quiz
 
Funny retirement slides
Funny retirement slidesFunny retirement slides
Funny retirement slides
 
Farewell powerpoint 2
Farewell powerpoint 2Farewell powerpoint 2
Farewell powerpoint 2
 
FAREWELL
FAREWELLFAREWELL
FAREWELL
 

Similar to Say Goodbye to Procedural Programming - Nick Sutterer

Where's My SQL? Designing Databases with ActiveRecord Migrations
Where's My SQL? Designing Databases with ActiveRecord MigrationsWhere's My SQL? Designing Databases with ActiveRecord Migrations
Where's My SQL? Designing Databases with ActiveRecord Migrations
Eleanor McHugh
 
Ruby/Rails
Ruby/RailsRuby/Rails
Ruby/Rails
rstankov
 
Ruby on Rails at PROMPT ISEL '11
Ruby on Rails at PROMPT ISEL '11Ruby on Rails at PROMPT ISEL '11
Ruby on Rails at PROMPT ISEL '11
Pedro Cunha
 
Código Saudável => Programador Feliz - Rs on Rails 2010
Código Saudável => Programador Feliz - Rs on Rails 2010Código Saudável => Programador Feliz - Rs on Rails 2010
Código Saudável => Programador Feliz - Rs on Rails 2010
Plataformatec
 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasminePaulo Ragonha
 
Why ruby
Why rubyWhy ruby
Why ruby
rstankov
 
SproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsSproutCore and the Future of Web Apps
SproutCore and the Future of Web Apps
Mike Subelsky
 
Design Summit - Rails 4 Migration - Aaron Patterson
Design Summit - Rails 4 Migration - Aaron PattersonDesign Summit - Rails 4 Migration - Aaron Patterson
Design Summit - Rails 4 Migration - Aaron Patterson
ManageIQ
 
Decent exposure: Controladores sin @ivars
Decent exposure: Controladores sin @ivarsDecent exposure: Controladores sin @ivars
Decent exposure: Controladores sin @ivarsLeonardo Soto
 
Intro To JavaScript Unit Testing - Ran Mizrahi
Intro To JavaScript Unit Testing - Ran MizrahiIntro To JavaScript Unit Testing - Ran Mizrahi
Intro To JavaScript Unit Testing - Ran MizrahiRan Mizrahi
 
Ruby on rails
Ruby on rails Ruby on rails
Ruby on rails
Mohit Jain
 
How To Test Everything
How To Test EverythingHow To Test Everything
How To Test Everything
noelrap
 
More to RoC weibo
More to RoC weiboMore to RoC weibo
More to RoC weibo
shaokun
 
SOLID Ruby, SOLID Rails
SOLID Ruby, SOLID RailsSOLID Ruby, SOLID Rails
SOLID Ruby, SOLID Rails
Jens-Christian Fischer
 
SproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsSproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsMike Subelsky
 
Avinash Kundaliya: Javascript and WordPress
Avinash Kundaliya: Javascript and WordPressAvinash Kundaliya: Javascript and WordPress
Avinash Kundaliya: Javascript and WordPresswpnepal
 
Django Vs Rails
Django Vs RailsDjango Vs Rails
Django Vs Rails
Sérgio Santos
 
QConSP 2015 - Dicas de Performance para Aplicações Web
QConSP 2015 - Dicas de Performance para Aplicações WebQConSP 2015 - Dicas de Performance para Aplicações Web
QConSP 2015 - Dicas de Performance para Aplicações Web
Fabio Akita
 
jQuery & 10,000 Global Functions: Working with Legacy JavaScript
jQuery & 10,000 Global Functions: Working with Legacy JavaScriptjQuery & 10,000 Global Functions: Working with Legacy JavaScript
jQuery & 10,000 Global Functions: Working with Legacy JavaScript
Guy Royse
 

Similar to Say Goodbye to Procedural Programming - Nick Sutterer (20)

Where's My SQL? Designing Databases with ActiveRecord Migrations
Where's My SQL? Designing Databases with ActiveRecord MigrationsWhere's My SQL? Designing Databases with ActiveRecord Migrations
Where's My SQL? Designing Databases with ActiveRecord Migrations
 
Ruby/Rails
Ruby/RailsRuby/Rails
Ruby/Rails
 
Ruby on Rails at PROMPT ISEL '11
Ruby on Rails at PROMPT ISEL '11Ruby on Rails at PROMPT ISEL '11
Ruby on Rails at PROMPT ISEL '11
 
Código Saudável => Programador Feliz - Rs on Rails 2010
Código Saudável => Programador Feliz - Rs on Rails 2010Código Saudável => Programador Feliz - Rs on Rails 2010
Código Saudável => Programador Feliz - Rs on Rails 2010
 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
 
Why ruby
Why rubyWhy ruby
Why ruby
 
SproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsSproutCore and the Future of Web Apps
SproutCore and the Future of Web Apps
 
Design Summit - Rails 4 Migration - Aaron Patterson
Design Summit - Rails 4 Migration - Aaron PattersonDesign Summit - Rails 4 Migration - Aaron Patterson
Design Summit - Rails 4 Migration - Aaron Patterson
 
Decent exposure: Controladores sin @ivars
Decent exposure: Controladores sin @ivarsDecent exposure: Controladores sin @ivars
Decent exposure: Controladores sin @ivars
 
Intro To JavaScript Unit Testing - Ran Mizrahi
Intro To JavaScript Unit Testing - Ran MizrahiIntro To JavaScript Unit Testing - Ran Mizrahi
Intro To JavaScript Unit Testing - Ran Mizrahi
 
Ruby on rails
Ruby on rails Ruby on rails
Ruby on rails
 
Django quickstart
Django quickstartDjango quickstart
Django quickstart
 
How To Test Everything
How To Test EverythingHow To Test Everything
How To Test Everything
 
More to RoC weibo
More to RoC weiboMore to RoC weibo
More to RoC weibo
 
SOLID Ruby, SOLID Rails
SOLID Ruby, SOLID RailsSOLID Ruby, SOLID Rails
SOLID Ruby, SOLID Rails
 
SproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsSproutCore and the Future of Web Apps
SproutCore and the Future of Web Apps
 
Avinash Kundaliya: Javascript and WordPress
Avinash Kundaliya: Javascript and WordPressAvinash Kundaliya: Javascript and WordPress
Avinash Kundaliya: Javascript and WordPress
 
Django Vs Rails
Django Vs RailsDjango Vs Rails
Django Vs Rails
 
QConSP 2015 - Dicas de Performance para Aplicações Web
QConSP 2015 - Dicas de Performance para Aplicações WebQConSP 2015 - Dicas de Performance para Aplicações Web
QConSP 2015 - Dicas de Performance para Aplicações Web
 
jQuery & 10,000 Global Functions: Working with Legacy JavaScript
jQuery & 10,000 Global Functions: Working with Legacy JavaScriptjQuery & 10,000 Global Functions: Working with Legacy JavaScript
jQuery & 10,000 Global Functions: Working with Legacy JavaScript
 

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 30
Ruby 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 29
Ruby 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 28
Ruby 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
 
The Trailblazer Ride from the If Jungle into a Civilised Railway Station - Or...
The Trailblazer Ride from the If Jungle into a Civilised Railway Station - Or...The Trailblazer Ride from the If Jungle into a Civilised Railway Station - Or...
The Trailblazer Ride from the If Jungle into a Civilised Railway Station - Or...
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 27
Ruby 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 26
Ruby 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 26
Ruby 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 26
Ruby 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 25
Ruby 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 Gusiev
Ruby 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 #23
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...
 
The Trailblazer Ride from the If Jungle into a Civilised Railway Station - Or...
The Trailblazer Ride from the If Jungle into a Civilised Railway Station - Or...The Trailblazer Ride from the If Jungle into a Civilised Railway Station - Or...
The Trailblazer Ride from the If Jungle into a Civilised Railway Station - Or...
 
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
 

Recently uploaded

20240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 202420240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 2024
Matthew Sinclair
 
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
James Anderson
 
Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1
DianaGray10
 
20240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 202420240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 2024
Matthew Sinclair
 
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
Neo4j
 
Enchancing adoption of Open Source Libraries. A case study on Albumentations.AI
Enchancing adoption of Open Source Libraries. A case study on Albumentations.AIEnchancing adoption of Open Source Libraries. A case study on Albumentations.AI
Enchancing adoption of Open Source Libraries. A case study on Albumentations.AI
Vladimir Iglovikov, Ph.D.
 
RESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for studentsRESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for students
KAMESHS29
 
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdfObservability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Paige Cruz
 
20240609 QFM020 Irresponsible AI Reading List May 2024
20240609 QFM020 Irresponsible AI Reading List May 202420240609 QFM020 Irresponsible AI Reading List May 2024
20240609 QFM020 Irresponsible AI Reading List May 2024
Matthew Sinclair
 
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
名前 です男
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
Safe Software
 
UiPath Test Automation using UiPath Test Suite series, part 5
UiPath Test Automation using UiPath Test Suite series, part 5UiPath Test Automation using UiPath Test Suite series, part 5
UiPath Test Automation using UiPath Test Suite series, part 5
DianaGray10
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
Ana-Maria Mihalceanu
 
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
SOFTTECHHUB
 
GridMate - End to end testing is a critical piece to ensure quality and avoid...
GridMate - End to end testing is a critical piece to ensure quality and avoid...GridMate - End to end testing is a critical piece to ensure quality and avoid...
GridMate - End to end testing is a critical piece to ensure quality and avoid...
ThomasParaiso2
 
Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !
KatiaHIMEUR1
 
How to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptxHow to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptx
danishmna97
 
Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
Alan Dix
 
Artificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopmentArtificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopment
Octavian Nadolu
 
Climate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing DaysClimate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing Days
Kari Kakkonen
 

Recently uploaded (20)

20240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 202420240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 2024
 
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
 
Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1
 
20240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 202420240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 2024
 
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
 
Enchancing adoption of Open Source Libraries. A case study on Albumentations.AI
Enchancing adoption of Open Source Libraries. A case study on Albumentations.AIEnchancing adoption of Open Source Libraries. A case study on Albumentations.AI
Enchancing adoption of Open Source Libraries. A case study on Albumentations.AI
 
RESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for studentsRESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for students
 
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdfObservability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
 
20240609 QFM020 Irresponsible AI Reading List May 2024
20240609 QFM020 Irresponsible AI Reading List May 202420240609 QFM020 Irresponsible AI Reading List May 2024
20240609 QFM020 Irresponsible AI Reading List May 2024
 
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
 
UiPath Test Automation using UiPath Test Suite series, part 5
UiPath Test Automation using UiPath Test Suite series, part 5UiPath Test Automation using UiPath Test Suite series, part 5
UiPath Test Automation using UiPath Test Suite series, part 5
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
 
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
 
GridMate - End to end testing is a critical piece to ensure quality and avoid...
GridMate - End to end testing is a critical piece to ensure quality and avoid...GridMate - End to end testing is a critical piece to ensure quality and avoid...
GridMate - End to end testing is a critical piece to ensure quality and avoid...
 
Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !
 
How to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptxHow to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptx
 
Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
 
Artificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopmentArtificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopment
 
Climate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing DaysClimate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing Days
 

Say Goodbye to Procedural Programming - Nick Sutterer

  • 1. SAY GOODBYE TO PROCEDURAL* PROGRAMMING ANOTHER USELESS PRESENTATION BROUGHT TO YOU BY @APOTONICK
  • 3.
  • 5. REVEAL.JS AND HOW TO MASTER IT, PART I OF VIII
  • 6. [ ] DIAGRAMS [ ] 6 MEMES [ ] 2 BULLET POINT LISTS [ ] QUOTE FROM SOMEONE [ ] MORE DIAGRAMS [ ] TRUCKLOADS OF CODE (you wanted it)
  • 7. [ ] DIAGRAMS [ ] 6 MEMES [x ] 2 BULLET POINT LISTS [ ] QUOTE FROM SOMEONE [ ] MORE DIAGRAMS [ ] TRUCKLOADS OF CODE (you wanted it)
  • 8.
  • 9.
  • 10.
  • 11.
  • 12. class Post < ActiveRecord::Base validates :body, presence:true validates :author, presence:true after_save :notify_moderators!, if: :create? end
  • 13.   class PostsController < ApplicationController def create return unless can?(current_user, Post, :new) post = Post.new(author: current_user) if post.update_attributes( params.require(:post).permit(:title) ) post.save notify_current_user! else render :new end end end
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24. Let's not talk about persistence! Let's not talk about business logic! Let's not talk about views!
  • 25.
  • 26. I SAID: RAILS VIEWS!
  • 27.
  • 28.
  • 29. Notes: let's come back to the problems in our example it's hard to understand what we are trying to do and:
  • 30. HOW DO I TEST THAT?
  • 31. class Post < ActiveRecord::Base validates :body, presence:true validates :author, presence:true after_save :notify_moderators!, if: :create? end describe Post do it "validates and notifies moderators" do post = Post.create( valid_params ) expect(post).to be_persisted end end
  • 32. class Post < ActiveRecord::Base validates :body, presence:true validates :author, presence:true after_save :notify_moderators!, if: :create? end describe Post do it "validates and notifies moderators" do post = Post.create( valid_params ) expect(post).to be_persisted end end
  • 33. it do controller = Controller.new controller.create( valid_params ) expect(Post.last).to be_persisted end
  • 34.
  • 35. describe BlogPostsController do it "creates BlogPost model" do post :create, blog_post: valid_params expect(response).to be_ok expect(BlogPost.last).to be_persisted end end
  • 36.
  • 39.
  • 40.
  • 41.
  • 42. [...] It extends the basic MVC pattern with new abstractions.
  • 43. NO!
  • 44.
  • 45.
  • 46.
  • 47.
  • 48. class MyService def self.call(args) # do something here end end MyService.( valid_params )
  • 49. Notes: we don't need any domain logic, that's very user specific and shouldn't be dictated by "my framework"
  • 50. class MyService def call(params) return unless can?(current_user, Post, :new) post = Post.new(author: current_user) post.update_attributes( params.require(:post).permit(:title) ) if post.save notify_current_user! end end end
  • 51.
  • 52. [ ] DIAGRAMS [x] 6 MEMES [x ] 2 BULLET POINT LISTS [ ] QUOTE FROM SOMEONE [ ] MORE DIAGRAMS [ ] TRUCKLOADS OF CODE (you wanted it)
  • 53. class MyService def call(params) return unless can?(current_user, Post, :new) post = Post.new(author: current_user) post.update_attributes( params.require(:post).permit(:title) ) if post.save notify_current_user! end end end
  • 54. TEST it do service = MyService.new service.call( valid_params ) expect(Post.last).to be_persisted end
  • 57. SERVICE OBJECTS, REVISITED [x] Encapsulation [x] Testing [ ] What to return? [ ] Validations extracted? [ ] Extendable class MyService def call(params) end end
  • 58. Is the problem the procedural* code design?
  • 59.
  • 60.
  • 61.
  • 62.
  • 65. OK, I GOT A QUESTION THEN:
  • 68. NO?
  • 69. class Create < Trailblazer::Operation # # # end
  • 70. class BlogPost::Create < Trailblazer::Operation # # # end
  • 71. class Create < Trailblazer::Operation # # # end
  • 72. class Create < Trailblazer::Operation def process(params) # sam's code here end end
  • 73. Notes: not really extendable
  • 74. class Create < Trailblazer::Operation def process(params) return unless can?(current_user, Post, :new) post = Post.new(author: current_user) post.update_attributes( params.require(:post).permit(:title) ) if post.save notify_current_user! end end end
  • 75. class Create < Trailblazer::Operation # # # end result = Create.() result.success? #=> true
  • 76. Notes: Hooray, we have an API for service objects!
  • 78. class Create < Trailblazer::Operation # # # # end
  • 79. class Create < Trailblazer::Operation step :create_model! step :validate! step :save! step :notify_current_user! end
  • 80.
  • 81.
  • 82. class Create < Trailblazer::Operation step :create_model! step :validate! step :save! step :notify_current_user! end
  • 83. class Create < Trailblazer::Operation step :create_model! # # # # end
  • 84. class Create < Trailblazer::Operation step :create_model! def create_model!(options, **) end end
  • 85. CREATE MODEL class Create < Trailblazer::Operation step :create_model! def create_model!(options, **) options["model"] = BlogPost.new end end result = Create.() result.success? #=> true result["model"] #=> #<BlogPost id:nil, ..>
  • 86. VALIDATE class Create < Trailblazer::Operation step :create_model! step :validate! def create_model!(options, **) # .. def validate!(options, params:, **) # validate params end end
  • 87. valid_params = { body: "Blogging's fun. #not" } Create.( valid_params ) class Create < Trailblazer::Operation # .. def validate!(options, params:, **) params #=> { body: "Blogging's fun. #not" } end end
  • 88. Notes: sending params into the op
  • 89. class Create < Trailblazer::Operation # .. def validate!(options, params:, **) model = options["model"] # from the create_model! step... if model.update_attributes(params) true else false end end end
  • 90. class Create < Trailblazer::Operation # .. def validate!(options, params:, model:, **) # # if model.update_attributes(params) true else false end end end
  • 91.
  • 92.
  • 93.
  • 94. #class Create < Trailblazer::Operation # .. def validate!(options, params:, model:, **) if model.update_attributes(params) true else false end end #end
  • 95. #class Create < Trailblazer::Operation # .. def validate!(options, params:, model:, **) # # # # model.update_attributes(params) end #end
  • 96.
  • 97.
  • 98. class Create < Trailblazer::Operation step :create_model! step :validate! step :save! # # # # # # end
  • 99. class Create < Trailblazer::Operation step :create_model! step :validate! step :save! #def create_model!(options, **) #def validate!(options, params:, **) def save!(options, params:, model:, **) true end end
  • 100.
  • 101.
  • 102. class Create < Trailblazer::Operation step :create_model! step :validate! step :save! step :notify! #def create_model!(options, **) #def validate!(options, params:, **) #def save!(options, params:, model:, **) def notify!(options, model:, **) MyMailer.call(model) end end
  • 105.
  • 106. class Create < Trailblazer::Operation step :create_model! step :validate! step :save! step :notify! #def create_model!(options, **) #def validate!(options, params:, **) #def save!(options, params:, model:, **) #def notify!(options, model:, **) end
  • 107. class Create < Trailblazer::Operation step :create_model! step :validate! [XXX] step :save! step :notify! #def create_model!(options, **) #def validate!(options, params:, **) #def save!(options, params:, model:, **) #def notify!(options, model:, **) end
  • 108.
  • 109.
  • 110. #class Create < Trailblazer::Operation # .. def validate!(options, params:, model:, **) model.update_attributes(params) #=> false end #end
  • 111.
  • 112.
  • 113.
  • 114. class Create < Trailblazer::Operation step :create_model! step :validate! step :save! step :notify! failure :handle! #.. end
  • 115. class Create < Trailblazer::Operation step :create_model! step :validate! step :save! step :notify! failure :handle! #.. def handle!(options, **) options["error"] = "don't cry!" end end
  • 116. result = Create.( { title: nil } ) result.success? #=> false result["error"] = "don't cry!"
  • 119. DUDE.
  • 120.
  • 121. Notes: do you find this more complex than this?
  • 122. class MyService def call(params) return unless can?(current_user, Post, :new) post = Post.new(author: current_user) if post.update_attributes( params.require(:post).permit(:title) ) unless notify_current_user! if ... else end end end
  • 123. class Create < Trailblazer::Operation step :create_model! step :validate! step :save! step :notify! failure :handle! # .. end
  • 124. def create_model!(options, **) def validate!( options, params:, **) def save!( options, params:, model:, **) def notify!( options, model:, **)
  • 125. result = Create.( { title: nil } ) result.success? #=> false result["error"] #=> "don't cry!" result["model"] #=> #<BlogPost title: nil>
  • 126. TEST it "fails with empty title" do result = Create.( { title: nil } ) expect(result).to be_success expect(result["error"]).to eq("don't cry!") expect(result["model"]).to be_persisted end
  • 128.
  • 129.
  • 131. class PostsController < ApplicationController def create return unless can?(current_user, Post, :new) post = Post.new(author: current_user) if post.update_attributes( params.require(:post).permit(:title)) notify_current_user! else render :new end end end
  • 132. class PostsController < ApplicationController def create return unless can?(current_user, Post, :new) # # # result = BlogPost::Create.( params ) if result.failure? render :new end end end
  • 133. AUTHORIZATION def create return unless can?(current_user, Post, :new) # ..
  • 134. class Create < Trailblazer::Operation step :authorize! #step :create_model! #step :validate! #step :save! #step :notify! #failure :handle! # .. end
  • 135. class Create < Trailblazer::Operation step :authorize! # .. def authorize!(options, current_user:, **) CouldCould.can?(current_user, Post, :new) end end
  • 137. def authorize!(options, current_user:, **) CouldCould.can?( current_user, # wtf? Post, :new ) end
  • 138. class PostsController < ApplicationController def create return unless can?(current_user, Post, :new) result = BlogPost::Create.( params ) # # # if result.failure? render :new end end end
  • 139. class PostsController < ApplicationController def create return unless can?(current_user, Post, :new) result = BlogPost::Create.( params, "current_user" => current_user ) if result.failure? render :new end end end
  • 140. class PostsController < ApplicationController def create #return unless can?(current_user, Post, :new) # result = BlogPost::Create.( params, "current_user" => current_user ) if result.failure? render :new end end end
  • 141. class PostsController < ApplicationController def create result = BlogPost::Create.( params, "current_user" => current_user ) if result.failure? render :new end end end
  • 142. class PostsController < ApplicationController def create run BlogPost::Create, "current_user" => current_user do return end render :new end end
  • 143. class PostsController < ApplicationController def create run BlogPost::Create do return end render :new end end
  • 144. class PostsController < ApplicationController def create run BlogPost::Create do |result| return redirect_to blog_post_path(result["model"].id) end render :new end end
  • 145. class PostsController < ApplicationController def create run BlogPost::Create do |result| return redirect_to blog_post_path(result["model" end render :new end end
  • 146. DEPENDENCY INJECTION it "works with current_user" do result = Create.( valid_params, "current_user" => User.find(1) ) # .. end
  • 147.
  • 148.
  • 149. class Create < Trailblazer::Operation step :authorize! # .. def authorize!(options, current_user:, **) CouldCould.can?(current_user, Post, :new) end end
  • 150. class Create < Trailblazer::Operation step MyAuth # .. class MyAuth def self.call(options, current_user:, **) CouldCould.can?(current_user, Post, :new) end end end
  • 151. class Create < Trailblazer::Operation step MyAuthCallableSittingSomewhere # .. #class MyAuth # def self.call(options, current_user:, **) # CouldCould.can?(current_user, Post, :new) # end #end end
  • 153. class Create < Trailblazer::Operation step Policy::CanCan( Post, :new ) # step :model! # .. end
  • 154.
  • 155.
  • 157.
  • 158. class Post < ActiveRecord::Base validates :title, presence:true validates :body, presence:true #after_save :notify_moderators!, if: :create? end
  • 159. module BlogPost module Contract class Create::Create < Reform::Form property :title property :body validates :title, presence:true validates :body, presence:true end end end
  • 160. class Create < Trailblazer::Operation step Policy::CanCan( Post, :new ) step :model! step :validate! step :notify! # .. def model!(options, **) def validate!(options, **) # .. end
  • 161. class Create < Trailblazer::Operation step Policy::CanCan( Post, :new ) step :model! step Contract::Build( constant: Contract::Create ) step Contract::Validate() step Contract::Persist() step :notify! # .. def model!(options, **) # .. end
  • 162.
  • 163.
  • 164.
  • 165.
  • 166. BPMN
  • 167.
  • 168.
  • 169.
  • 170.
  • 171.
  • 172. class Create < Trailblazer::Operation step :create_model! step :validate! step :save! step :notify! failure :handle! # .. end
  • 173.
  • 177. [ ] DIAGRAMS [x] 6 MEMES [xX] 2 BULLET POINT LISTS [x] QUOTE FROM SOMEONE [x] MORE DIAGRAMS [ ] TRUCKLOADS OF CODE (you wanted it)