SlideShare a Scribd company logo
March 22nd, 2013

A Rails Criticism
how i learned to stop worrying about the Golden Path
                                       Luca Guidi
AGENDA




intro
Luca Guidi
 Senior Developer at Litmus
  @jodosha - http//lucag uidi.com
litmus
Beautiful Email previews
  Campaig n analytics
   Spam filter tests
 HTML code analysis
   And many other..
Why Rails
has revolutionized web
     development?
         (IMHO)
Why Rails
  has revolutionized web
       development?


Convention Over
 Config uration
          (IMHO)

           :)
Why Rails
     has revolutionized web
          development?


Dynamic and innovative
   Convention Over
    Config uration
     ecosystem
             (IMHO)

              :)
Why Rails
     has revolutionized web
          development?


Dynamic and innovative
   Convention Over
   Productivity and
 Developer uration
    Config Happiness
      ecosystem
             (IMHO)
             :)
..but




The Framework is almost
      ten years old
..but




TheLot of Legacy Code
 A Framework is almost
     ten years old
       is around
..but




TheLot of Legacymajor
 A Frameworkais Code
  Upgrades to     almost
 release years old
     ten are *painful*
       is around
AGENDA




intro   problems
Active
 Record



Active
Record
Active
       Record




Models != Records
Active
                     Record




 Encapsulation violations
1 if article.statearticle.published?
        1 unless != 'published'
2   article.update_attribute(state: 'published')
        2   article.publish!
3 end   3 end
       4 # not completely right...
Active
                     Record

 Encapsulation violations
1 if article.statearticle.published?
        1 unless != 'published'
2   article.update_attribute(state: 'published')
        2   article.publish!
3 end   3 end
       4 # not completely right...
Active
                     Record

 Encapsulation violations
1 if article.statearticle.published?
        1 unless != 'published'
2   article.update_attribute(state: 'published')
        2   article.publish!
3 end   3 end
       4 # not completely right...
Active
            Record



  Tell, Don’t Ask
1
2     violations
 article.publish!
 unless article.published?
 # article.publish!
   push the implementation
3 end
  # into the model
4 # not completely right...
Active
              Record
    Tell, Don’t Ask
      violations
1   article.publish!
    unless article.published?
2   # article.publish!
      push the implementation
3   end
    # into the model
4   # not completely right...
Active
              Record
    Tell, Don’t Ask
      violations
1   article.publish!
    unless article.published?
2   # article.publish!
      push the implementation
3   end
    # into the model
4   # not completely right...
Active
                          Record




2
   Implicit vs Explicit API
1 class Post < ActiveRecord::Base
     1 Post.where(state:'published').
          1 Post.most_recent_published
    def self.most_recent_published(limit = 5)
3    2published.recent(limit).order('created_at DESC')
               order('created_at DESC').
4   end
5    3         limit(5)
6   private
7   scope :published, ->() { where(state: 'published') }
8   scope :recent,    ->(n) { limit(n) }
9 end
Active
                          Record


   Implicit vs Explicit API
1 class Post < ActiveRecord::Base
2    1 Post.where(state:'published').
          1 Post.most_recent_published
    def self.most_recent_published(limit = 5)
3    2published.recent(limit).order('created_at DESC')
               order('created_at DESC').
4   end
5    3         limit(5)
6   private
7   scope :published, ->() { where(state: 'published') }
8   scope :recent,    ->(n) { limit(n) }
9 end
Active
                          Record


   Implicit vs Explicit API
1 class Post < ActiveRecord::Base
2    1 Post.where(state:'published').
          1 Post.most_recent_published
    def self.most_recent_published(limit = 5)
3    2published.recent(limit).order('created_at DESC')
               order('created_at DESC').
4   end
5    3         limit(5)
6   private
7   scope :published, ->() { where(state: 'published') }
8   scope :recent,    ->(n) { limit(n) }
9 end
Active
                          Record


   Implicit vs Explicit API
1 class Post < ActiveRecord::Base
2    1 Post.where(state:'published').
          1 Post.most_recent_published
    def self.most_recent_published(limit = 5)
3    2published.recent(limit).order('created_at DESC')
               order('created_at DESC').
4   end
5    3         limit(5)
6   private
7   scope :published, ->() { where(state: 'published') }
8   scope :recent,    ->(n) { limit(n) }
9 end
Active
      Record




Callbacks abuse
               Non-persistence logic is
               tight to the persistence
               life cycle.

               Eg. Sending emails
Active
       Record




Testability issues
                Micheal Feathers
Active
                Record



A test is not a unit test if it talks
      Testability issues
          to a database.
                          Micheal Feathers
Action
  Controller



 Action
Controller
        It doesn’t affect too much your
        architecture, but it has strange
        OOP design.
Action
                                  Controller


1 class PostsController < ApplicationController
2    before_filter :authenticate


 Frankenstein Controllers
3
4    def new
5    end
6
7    def create
8      @post = Post.new(params[:post])
9
10     if @post.save
11       redirect_to post_url(@post), notice: 'Yay!'
12     else
13       render :new
14     end
15   end
16 end
Action
                                  Controller

 Frankenstein Controllers
1 class PostsController < ApplicationController
2    before_filter :authenticate
3
4    def new
5    end
6
7    def create
8      @post = Post.new(params[:post])
9
10     if @post.save
11       redirect_to post_url(@post), notice: 'Yay!'
12     else
13       render :new
14     end
15   end
16 end
Action
                                  Controller

 Frankenstein Controllers
1 class PostsController < ApplicationController
2    before_filter :authenticate
3
4    def new
5    end
6
7    def create
8      @post = Post.new(params[:post])
9
10     if @post.save
11       redirect_to post_url(@post), notice: 'Yay!'
12     else
13       render :new
14     end
15   end
16 end
Action
                                  Controller

 Frankenstein Controllers
1 class PostsController < ApplicationController
2    before_filter :authenticate
3
4    def new
5    end
6
7    def create
8      @post = Post.new(params[:post])
9
10     if @post.save
11       redirect_to post_url(@post), notice: 'Yay!'
12     else
13       render :new
14     end
15   end
16 end
Action
                                  Controller

 Frankenstein Controllers
1 class PostsController < ApplicationController
2    before_filter :authenticate
3
4    def new
5    end
6
7    def create
8      @post = Post.new(params[:post])
9
10     if @post.save
11       redirect_to post_url(@post), notice: 'Yay!'
12     else
13       render :new
14     end
15   end
16 end
Action
                                  Controller

 Frankenstein Controllers
1 class PostsController < ApplicationController
2    before_filter :authenticate
3
4    def new
5    end
6
7    def create
8      @post = Post.new(params[:post])
9
10     if @post.save
11       redirect_to post_url(@post), notice: 'Yay!'
12     else
13       render :new
14     end
15   end
16 end
Action
                                 Controller


1 class PostsController < ApplicationController
2    # ...


                    Odd classes
3
4    def create
5      @post = Post.new(params[:post])
6
7      if @post.save
8        # ...
9      else
10       # ...
11     end
12   end
13 end
Action
                                 Controller

                    Odd classes
1 class PostsController < ApplicationController
2    # ...
3
4    def create
5      @post = Post.new(params[:post])
6
7      if @post.save
8        # ...
9      else
10       # ...
11     end
12   end
13 end
Action
                                 Controller

                    Odd classes
1 class PostsController < ApplicationController
2    # ...
3
4    def create
5      @post = Post.new(params[:post])
6
7      if @post.save
8        # ...
9      else
10       # ...
11     end
12   end
13 end
Action
                                 Controller

                    Odd classes
1 class PostsController < ApplicationController
2    # ...
3
4    def create
5      @post = Post.new(params[:post])
6
7      if @post.save
8        # ...
9      else
10       # ...
11     end
12   end
13 end
Action
                                  Controller




3
4
 Encapsulation violations
1 class PostsController < ApplicationController
2   # ...

    def create
5     @post = Post.new(params[:post])
6     # ...
7   end
8 end
Action
                                  Controller

 Encapsulation violations
1 class PostsController < ApplicationController
2   # ...
3
4   def create
5     @post = Post.new(params[:post])
6     # ...
7   end
8 end
Action
                        Controller


1 describe PostsController do


         Testability issues
2   it 'assigns @posts' do
3     Post.should_receive(:most_recent_published).
4       and_return(posts = [mock])
5     get :index
6
7     expect(assigns(:posts)).to eq(posts)
8   end
9 end
Action
                        Controller

         Testability issues
1 describe PostsController do
2   it 'assigns @posts' do
3     Post.should_receive(:most_recent_published).
4       and_return(posts = [mock])
5     get :index
6
7     expect(assigns(:posts)).to eq(posts)
8   end
9 end
Action
                        Controller

         Testability issues
1 describe PostsController do
2   it 'assigns @posts' do
3     Post.should_receive(:most_recent_published).
4       and_return(posts = [mock])
5     get :index
6
7     expect(assigns(:posts)).to eq(posts)
8   end
9 end
Action
                        Controller

         Testability issues
1 describe PostsController do
2   it 'assigns @posts' do
3     Post.should_receive(:most_recent_published).
4       and_return(posts = [mock])
5     get :index
6
7     expect(assigns(:posts)).to eq(posts)
8   end
9 end
Action
                        Controller

         Testability issues
1 describe PostsController do
2   it 'assigns @posts' do
3     Post.should_receive(:most_recent_published).
4       and_return(posts = [mock])
5     get :index
6
7     expect(assigns(:posts)).to eq(posts)
8   end
9 end
Action
                        Controller

         Testability issues
1 describe PostsController do
2   it 'assigns @posts' do
3     Post.should_receive(:most_recent_published).
4       and_return(posts = [mock])
5     get :index
6
7     expect(assigns(:posts)).to eq(posts)
8   end
9 end
Action
 View



Action
View
Action
                                View




       Views aren’t views
                     (but templates with logic)

Without “real” views (or                     In an ideal world we
presenters), we’re tempted to                shouldn’t test our
push presentational methods                  templates.
into the models.
Action
                             View



          Helpers are
    functional programming
1   def user_full_name(user)
2     [ user.first_name, user.last_name ].join(' ')
3   end
4
5   url_for
6   # vs                                 Half-assed way to solve
7   Url.for                              presentational problems in
8                                        ActionView.
9   posts_url
Action
                             View
          Helpers are
    functional programming
1   def user_full_name(user)
2     [ user.first_name, user.last_name ].join(' ')
3   end
4
5   url_for
6   # vs                                 Half-assed way to solve
7   Url.for                              presentational problems in
8                                        ActionView.
9   posts_url
Ruby on
  Rails



Ruby on
 Rails
Ruby on
           Rails


Rails isn’t a framework,
  but an application
        template
Ruby on
           Rails



Rails is multi-paradig m
       as Ruby is.
AGENDA




intro   problems   solutions
Solutions



Decouple your logic from
ActiveRecord as much as
        possible.
                      AR is focused on data, but
                      OOP is about behavior.
Solutions




   Don’t think in
ActiveRecord terms.
                   Database is a detail,
                   forget about associations,
                   scopes, validations..
Solutions




Let your public API
 to declare intents.
                   Let your design to emerge
                   via TDD.
Solutions



 Keep methods and
accessors private as
 much as possible.
                    Public APIs are hard to
                    maintain as the codebase
                    and the team grows.
Solutions



Skinny controllers
       and
 skinny models.
             Use ser vice objects or DCI, they
             are easier and faster to test.
Solutions



Don’t be afraid to extract
  ad-hoc classes for
specific responsibilities.
                 Inner classes are your friends,
                 they help you with details, and
                 aren’t part of your public API.
Solutions




Use DIY presenters
            They will help you to keep your
            models clean from presentational
            logic.
Solutions




Refactor, refactor,
    refactor.
AGENDA




intro   problems   solutions   conclusion
Q&A
me@lucag uidi.com
         @jodosha
https://speakerdeck.com/jodosha/a-rails-criticism

               Except where otherwise noted, this work is licensed under:
                   http://creativecommons.org/licenses/by-nc-sa/3.0/
Una Critica a Rails by Luca Guidi

More Related Content

What's hot

Java8 tgtbatu javaone
Java8 tgtbatu javaoneJava8 tgtbatu javaone
Java8 tgtbatu javaone
Brian Vermeer
 
The Ring programming language version 1.5.3 book - Part 13 of 184
The Ring programming language version 1.5.3 book - Part 13 of 184The Ring programming language version 1.5.3 book - Part 13 of 184
The Ring programming language version 1.5.3 book - Part 13 of 184
Mahmoud Samir Fayed
 
Advanced Jasmine - Front-End JavaScript Unit Testing
Advanced Jasmine - Front-End JavaScript Unit TestingAdvanced Jasmine - Front-End JavaScript Unit Testing
Advanced Jasmine - Front-End JavaScript Unit Testing
Lars Thorup
 
Intro to Unit Testing in AngularJS
Intro to Unit Testing in AngularJSIntro to Unit Testing in AngularJS
Intro to Unit Testing in AngularJS
Jim Lynch
 
PgTAP Best Practices
PgTAP Best PracticesPgTAP Best Practices
PgTAP Best Practices
David Wheeler
 
Test-Driven Development of AngularJS Applications
Test-Driven Development of AngularJS ApplicationsTest-Driven Development of AngularJS Applications
Test-Driven Development of AngularJS Applications
FITC
 
Software engineering ⊇ Software testing
Software engineering ⊇ Software testingSoftware engineering ⊇ Software testing
Software engineering ⊇ Software testing
Pavel Tcholakov
 
Java(8) The Good, The Bad and the Ugly
Java(8) The Good, The Bad and the UglyJava(8) The Good, The Bad and the Ugly
Java(8) The Good, The Bad and the Ugly
Brian Vermeer
 
RSpec 3.0: Under the Covers
RSpec 3.0: Under the CoversRSpec 3.0: Under the Covers
RSpec 3.0: Under the Covers
Brian Gesiak
 
Javascript Testing with Jasmine 101
Javascript Testing with Jasmine 101Javascript Testing with Jasmine 101
Javascript Testing with Jasmine 101
Roy Yu
 
Legacy Code Kata v3.0
Legacy Code Kata v3.0Legacy Code Kata v3.0
Legacy Code Kata v3.0
William Munn
 
Legacy Dependency Kata v2.0
Legacy Dependency Kata v2.0Legacy Dependency Kata v2.0
Legacy Dependency Kata v2.0
William Munn
 
Qunit Java script Un
Qunit Java script UnQunit Java script Un
Qunit Java script Un
akanksha arora
 
The Ring programming language version 1.8 book - Part 89 of 202
The Ring programming language version 1.8 book - Part 89 of 202The Ring programming language version 1.8 book - Part 89 of 202
The Ring programming language version 1.8 book - Part 89 of 202
Mahmoud Samir Fayed
 
Firebase ng2 zurich
Firebase ng2 zurichFirebase ng2 zurich
Firebase ng2 zurich
Christoffer Noring
 
Full Stack Unit Testing
Full Stack Unit TestingFull Stack Unit Testing
Full Stack Unit Testing
GlobalLogic Ukraine
 
Stop Making Excuses and Start Testing Your JavaScript
Stop Making Excuses and Start Testing Your JavaScriptStop Making Excuses and Start Testing Your JavaScript
Stop Making Excuses and Start Testing Your JavaScript
Ryan Anklam
 
Martin Anderson - threads v actors
Martin Anderson - threads v actorsMartin Anderson - threads v actors
Martin Anderson - threads v actors
bloodredsun
 
Angularjs - Unit testing introduction
Angularjs - Unit testing introductionAngularjs - Unit testing introduction
Angularjs - Unit testing introduction
Nir Kaufman
 
FullStack Reativo com Spring WebFlux + Angular
FullStack Reativo com Spring WebFlux + AngularFullStack Reativo com Spring WebFlux + Angular
FullStack Reativo com Spring WebFlux + Angular
Loiane Groner
 

What's hot (20)

Java8 tgtbatu javaone
Java8 tgtbatu javaoneJava8 tgtbatu javaone
Java8 tgtbatu javaone
 
The Ring programming language version 1.5.3 book - Part 13 of 184
The Ring programming language version 1.5.3 book - Part 13 of 184The Ring programming language version 1.5.3 book - Part 13 of 184
The Ring programming language version 1.5.3 book - Part 13 of 184
 
Advanced Jasmine - Front-End JavaScript Unit Testing
Advanced Jasmine - Front-End JavaScript Unit TestingAdvanced Jasmine - Front-End JavaScript Unit Testing
Advanced Jasmine - Front-End JavaScript Unit Testing
 
Intro to Unit Testing in AngularJS
Intro to Unit Testing in AngularJSIntro to Unit Testing in AngularJS
Intro to Unit Testing in AngularJS
 
PgTAP Best Practices
PgTAP Best PracticesPgTAP Best Practices
PgTAP Best Practices
 
Test-Driven Development of AngularJS Applications
Test-Driven Development of AngularJS ApplicationsTest-Driven Development of AngularJS Applications
Test-Driven Development of AngularJS Applications
 
Software engineering ⊇ Software testing
Software engineering ⊇ Software testingSoftware engineering ⊇ Software testing
Software engineering ⊇ Software testing
 
Java(8) The Good, The Bad and the Ugly
Java(8) The Good, The Bad and the UglyJava(8) The Good, The Bad and the Ugly
Java(8) The Good, The Bad and the Ugly
 
RSpec 3.0: Under the Covers
RSpec 3.0: Under the CoversRSpec 3.0: Under the Covers
RSpec 3.0: Under the Covers
 
Javascript Testing with Jasmine 101
Javascript Testing with Jasmine 101Javascript Testing with Jasmine 101
Javascript Testing with Jasmine 101
 
Legacy Code Kata v3.0
Legacy Code Kata v3.0Legacy Code Kata v3.0
Legacy Code Kata v3.0
 
Legacy Dependency Kata v2.0
Legacy Dependency Kata v2.0Legacy Dependency Kata v2.0
Legacy Dependency Kata v2.0
 
Qunit Java script Un
Qunit Java script UnQunit Java script Un
Qunit Java script Un
 
The Ring programming language version 1.8 book - Part 89 of 202
The Ring programming language version 1.8 book - Part 89 of 202The Ring programming language version 1.8 book - Part 89 of 202
The Ring programming language version 1.8 book - Part 89 of 202
 
Firebase ng2 zurich
Firebase ng2 zurichFirebase ng2 zurich
Firebase ng2 zurich
 
Full Stack Unit Testing
Full Stack Unit TestingFull Stack Unit Testing
Full Stack Unit Testing
 
Stop Making Excuses and Start Testing Your JavaScript
Stop Making Excuses and Start Testing Your JavaScriptStop Making Excuses and Start Testing Your JavaScript
Stop Making Excuses and Start Testing Your JavaScript
 
Martin Anderson - threads v actors
Martin Anderson - threads v actorsMartin Anderson - threads v actors
Martin Anderson - threads v actors
 
Angularjs - Unit testing introduction
Angularjs - Unit testing introductionAngularjs - Unit testing introduction
Angularjs - Unit testing introduction
 
FullStack Reativo com Spring WebFlux + Angular
FullStack Reativo com Spring WebFlux + AngularFullStack Reativo com Spring WebFlux + Angular
FullStack Reativo com Spring WebFlux + Angular
 

Similar to Una Critica a Rails by Luca Guidi

Aprendendo solid com exemplos
Aprendendo solid com exemplosAprendendo solid com exemplos
Aprendendo solid com exemplos
vinibaggio
 
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
 
RSpec
RSpecRSpec
Testing Legacy Rails Apps
Testing Legacy Rails AppsTesting Legacy Rails Apps
Testing Legacy Rails Apps
Rabble .
 
Ruby: OOP, metaprogramming, blocks, iterators, mix-ins, duck typing. Code style
Ruby: OOP, metaprogramming, blocks, iterators, mix-ins, duck typing. Code styleRuby: OOP, metaprogramming, blocks, iterators, mix-ins, duck typing. Code style
Ruby: OOP, metaprogramming, blocks, iterators, mix-ins, duck typing. Code style
Anton Shemerey
 
How To Test Everything
How To Test EverythingHow To Test Everything
How To Test Everything
noelrap
 
Ruby/Rails
Ruby/RailsRuby/Rails
Ruby/Rails
rstankov
 
Checking Clang 11 with PVS-Studio
Checking Clang 11 with PVS-StudioChecking Clang 11 with PVS-Studio
Checking Clang 11 with PVS-Studio
Andrey Karpov
 
Java7
Java7Java7
Migrating legacy data
Migrating legacy dataMigrating legacy data
Migrating legacy data
Patrick Huesler
 
Writing Macros
Writing MacrosWriting Macros
Writing Macros
RueiCi Wang
 
Rails 3 Beautiful Code
Rails 3 Beautiful CodeRails 3 Beautiful Code
Rails 3 Beautiful Code
GreggPollack
 
Why ruby
Why rubyWhy ruby
Why ruby
rstankov
 
GeeCON 2017 - TestContainers. Integration testing without the hassle
GeeCON 2017 - TestContainers. Integration testing without the hassleGeeCON 2017 - TestContainers. Integration testing without the hassle
GeeCON 2017 - TestContainers. Integration testing without the hassle
Anton Arhipov
 
JavaScript Cheatsheets with easy way .pdf
JavaScript Cheatsheets with easy way .pdfJavaScript Cheatsheets with easy way .pdf
JavaScript Cheatsheets with easy way .pdf
ranjanadeore1
 
Workshop React.js
Workshop React.jsWorkshop React.js
Workshop React.js
Commit University
 
Aligning Ember.js with Web Standards
Aligning Ember.js with Web StandardsAligning Ember.js with Web Standards
Aligning Ember.js with Web Standards
Matthew Beale
 
TDD & BDD
TDD & BDDTDD & BDD
TDD & BDD
Arvind Vyas
 
Troubleshooting tips from docker support engineers
Troubleshooting tips from docker support engineersTroubleshooting tips from docker support engineers
Troubleshooting tips from docker support engineers
Docker, Inc.
 
Fundamental Concepts of React JS for Beginners.pdf
Fundamental Concepts of React JS for Beginners.pdfFundamental Concepts of React JS for Beginners.pdf
Fundamental Concepts of React JS for Beginners.pdf
StephieJohn
 

Similar to Una Critica a Rails by Luca Guidi (20)

Aprendendo solid com exemplos
Aprendendo solid com exemplosAprendendo solid com exemplos
Aprendendo solid com exemplos
 
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
 
RSpec
RSpecRSpec
RSpec
 
Testing Legacy Rails Apps
Testing Legacy Rails AppsTesting Legacy Rails Apps
Testing Legacy Rails Apps
 
Ruby: OOP, metaprogramming, blocks, iterators, mix-ins, duck typing. Code style
Ruby: OOP, metaprogramming, blocks, iterators, mix-ins, duck typing. Code styleRuby: OOP, metaprogramming, blocks, iterators, mix-ins, duck typing. Code style
Ruby: OOP, metaprogramming, blocks, iterators, mix-ins, duck typing. Code style
 
How To Test Everything
How To Test EverythingHow To Test Everything
How To Test Everything
 
Ruby/Rails
Ruby/RailsRuby/Rails
Ruby/Rails
 
Checking Clang 11 with PVS-Studio
Checking Clang 11 with PVS-StudioChecking Clang 11 with PVS-Studio
Checking Clang 11 with PVS-Studio
 
Java7
Java7Java7
Java7
 
Migrating legacy data
Migrating legacy dataMigrating legacy data
Migrating legacy data
 
Writing Macros
Writing MacrosWriting Macros
Writing Macros
 
Rails 3 Beautiful Code
Rails 3 Beautiful CodeRails 3 Beautiful Code
Rails 3 Beautiful Code
 
Why ruby
Why rubyWhy ruby
Why ruby
 
GeeCON 2017 - TestContainers. Integration testing without the hassle
GeeCON 2017 - TestContainers. Integration testing without the hassleGeeCON 2017 - TestContainers. Integration testing without the hassle
GeeCON 2017 - TestContainers. Integration testing without the hassle
 
JavaScript Cheatsheets with easy way .pdf
JavaScript Cheatsheets with easy way .pdfJavaScript Cheatsheets with easy way .pdf
JavaScript Cheatsheets with easy way .pdf
 
Workshop React.js
Workshop React.jsWorkshop React.js
Workshop React.js
 
Aligning Ember.js with Web Standards
Aligning Ember.js with Web StandardsAligning Ember.js with Web Standards
Aligning Ember.js with Web Standards
 
TDD & BDD
TDD & BDDTDD & BDD
TDD & BDD
 
Troubleshooting tips from docker support engineers
Troubleshooting tips from docker support engineersTroubleshooting tips from docker support engineers
Troubleshooting tips from docker support engineers
 
Fundamental Concepts of React JS for Beginners.pdf
Fundamental Concepts of React JS for Beginners.pdfFundamental Concepts of React JS for Beginners.pdf
Fundamental Concepts of React JS for Beginners.pdf
 

More from Codemotion

Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
Codemotion
 
Pompili - From hero to_zero: The FatalNoise neverending story
Pompili - From hero to_zero: The FatalNoise neverending storyPompili - From hero to_zero: The FatalNoise neverending story
Pompili - From hero to_zero: The FatalNoise neverending story
Codemotion
 
Pastore - Commodore 65 - La storia
Pastore - Commodore 65 - La storiaPastore - Commodore 65 - La storia
Pastore - Commodore 65 - La storia
Codemotion
 
Pennisi - Essere Richard Altwasser
Pennisi - Essere Richard AltwasserPennisi - Essere Richard Altwasser
Pennisi - Essere Richard Altwasser
Codemotion
 
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Codemotion
 
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Codemotion
 
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Codemotion
 
Francesco Baldassarri - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Francesco Baldassarri  - Deliver Data at Scale - Codemotion Amsterdam 2019 - Francesco Baldassarri  - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Francesco Baldassarri - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Codemotion
 
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Codemotion
 
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Codemotion
 
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Codemotion
 
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Codemotion
 
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Codemotion
 
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Codemotion
 
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Codemotion
 
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
Codemotion
 
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Codemotion
 
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Codemotion
 
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Codemotion
 
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Codemotion
 

More from Codemotion (20)

Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
 
Pompili - From hero to_zero: The FatalNoise neverending story
Pompili - From hero to_zero: The FatalNoise neverending storyPompili - From hero to_zero: The FatalNoise neverending story
Pompili - From hero to_zero: The FatalNoise neverending story
 
Pastore - Commodore 65 - La storia
Pastore - Commodore 65 - La storiaPastore - Commodore 65 - La storia
Pastore - Commodore 65 - La storia
 
Pennisi - Essere Richard Altwasser
Pennisi - Essere Richard AltwasserPennisi - Essere Richard Altwasser
Pennisi - Essere Richard Altwasser
 
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
 
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
 
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
 
Francesco Baldassarri - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Francesco Baldassarri  - Deliver Data at Scale - Codemotion Amsterdam 2019 - Francesco Baldassarri  - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Francesco Baldassarri - Deliver Data at Scale - Codemotion Amsterdam 2019 -
 
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
 
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
 
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
 
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
 
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
 
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
 
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
 
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
 
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
 
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
 
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
 
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
 

Recently uploaded

Crafting Excellence: A Comprehensive Guide to iOS Mobile App Development Serv...
Crafting Excellence: A Comprehensive Guide to iOS Mobile App Development Serv...Crafting Excellence: A Comprehensive Guide to iOS Mobile App Development Serv...
Crafting Excellence: A Comprehensive Guide to iOS Mobile App Development Serv...
Pitangent Analytics & Technology Solutions Pvt. Ltd
 
Digital Banking in the Cloud: How Citizens Bank Unlocked Their Mainframe
Digital Banking in the Cloud: How Citizens Bank Unlocked Their MainframeDigital Banking in the Cloud: How Citizens Bank Unlocked Their Mainframe
Digital Banking in the Cloud: How Citizens Bank Unlocked Their Mainframe
Precisely
 
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectorsConnector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
DianaGray10
 
Deep Dive: AI-Powered Marketing to Get More Leads and Customers with HyperGro...
Deep Dive: AI-Powered Marketing to Get More Leads and Customers with HyperGro...Deep Dive: AI-Powered Marketing to Get More Leads and Customers with HyperGro...
Deep Dive: AI-Powered Marketing to Get More Leads and Customers with HyperGro...
saastr
 
Freshworks Rethinks NoSQL for Rapid Scaling & Cost-Efficiency
Freshworks Rethinks NoSQL for Rapid Scaling & Cost-EfficiencyFreshworks Rethinks NoSQL for Rapid Scaling & Cost-Efficiency
Freshworks Rethinks NoSQL for Rapid Scaling & Cost-Efficiency
ScyllaDB
 
"Choosing proper type of scaling", Olena Syrota
"Choosing proper type of scaling", Olena Syrota"Choosing proper type of scaling", Olena Syrota
"Choosing proper type of scaling", Olena Syrota
Fwdays
 
Fueling AI with Great Data with Airbyte Webinar
Fueling AI with Great Data with Airbyte WebinarFueling AI with Great Data with Airbyte Webinar
Fueling AI with Great Data with Airbyte Webinar
Zilliz
 
HCL Notes and Domino License Cost Reduction in the World of DLAU
HCL Notes and Domino License Cost Reduction in the World of DLAUHCL Notes and Domino License Cost Reduction in the World of DLAU
HCL Notes and Domino License Cost Reduction in the World of DLAU
panagenda
 
Essentials of Automations: Exploring Attributes & Automation Parameters
Essentials of Automations: Exploring Attributes & Automation ParametersEssentials of Automations: Exploring Attributes & Automation Parameters
Essentials of Automations: Exploring Attributes & Automation Parameters
Safe Software
 
Programming Foundation Models with DSPy - Meetup Slides
Programming Foundation Models with DSPy - Meetup SlidesProgramming Foundation Models with DSPy - Meetup Slides
Programming Foundation Models with DSPy - Meetup Slides
Zilliz
 
GNSS spoofing via SDR (Criptored Talks 2024)
GNSS spoofing via SDR (Criptored Talks 2024)GNSS spoofing via SDR (Criptored Talks 2024)
GNSS spoofing via SDR (Criptored Talks 2024)
Javier Junquera
 
Leveraging the Graph for Clinical Trials and Standards
Leveraging the Graph for Clinical Trials and StandardsLeveraging the Graph for Clinical Trials and Standards
Leveraging the Graph for Clinical Trials and Standards
Neo4j
 
Y-Combinator seed pitch deck template PP
Y-Combinator seed pitch deck template PPY-Combinator seed pitch deck template PP
Y-Combinator seed pitch deck template PP
c5vrf27qcz
 
AppSec PNW: Android and iOS Application Security with MobSF
AppSec PNW: Android and iOS Application Security with MobSFAppSec PNW: Android and iOS Application Security with MobSF
AppSec PNW: Android and iOS Application Security with MobSF
Ajin Abraham
 
5th LF Energy Power Grid Model Meet-up Slides
5th LF Energy Power Grid Model Meet-up Slides5th LF Energy Power Grid Model Meet-up Slides
5th LF Energy Power Grid Model Meet-up Slides
DanBrown980551
 
Mutation Testing for Task-Oriented Chatbots
Mutation Testing for Task-Oriented ChatbotsMutation Testing for Task-Oriented Chatbots
Mutation Testing for Task-Oriented Chatbots
Pablo Gómez Abajo
 
Energy Efficient Video Encoding for Cloud and Edge Computing Instances
Energy Efficient Video Encoding for Cloud and Edge Computing InstancesEnergy Efficient Video Encoding for Cloud and Edge Computing Instances
Energy Efficient Video Encoding for Cloud and Edge Computing Instances
Alpen-Adria-Universität
 
JavaLand 2024: Application Development Green Masterplan
JavaLand 2024: Application Development Green MasterplanJavaLand 2024: Application Development Green Masterplan
JavaLand 2024: Application Development Green Masterplan
Miro Wengner
 
Harnessing the Power of NLP and Knowledge Graphs for Opioid Research
Harnessing the Power of NLP and Knowledge Graphs for Opioid ResearchHarnessing the Power of NLP and Knowledge Graphs for Opioid Research
Harnessing the Power of NLP and Knowledge Graphs for Opioid Research
Neo4j
 
"Frontline Battles with DDoS: Best practices and Lessons Learned", Igor Ivaniuk
"Frontline Battles with DDoS: Best practices and Lessons Learned",  Igor Ivaniuk"Frontline Battles with DDoS: Best practices and Lessons Learned",  Igor Ivaniuk
"Frontline Battles with DDoS: Best practices and Lessons Learned", Igor Ivaniuk
Fwdays
 

Recently uploaded (20)

Crafting Excellence: A Comprehensive Guide to iOS Mobile App Development Serv...
Crafting Excellence: A Comprehensive Guide to iOS Mobile App Development Serv...Crafting Excellence: A Comprehensive Guide to iOS Mobile App Development Serv...
Crafting Excellence: A Comprehensive Guide to iOS Mobile App Development Serv...
 
Digital Banking in the Cloud: How Citizens Bank Unlocked Their Mainframe
Digital Banking in the Cloud: How Citizens Bank Unlocked Their MainframeDigital Banking in the Cloud: How Citizens Bank Unlocked Their Mainframe
Digital Banking in the Cloud: How Citizens Bank Unlocked Their Mainframe
 
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectorsConnector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
 
Deep Dive: AI-Powered Marketing to Get More Leads and Customers with HyperGro...
Deep Dive: AI-Powered Marketing to Get More Leads and Customers with HyperGro...Deep Dive: AI-Powered Marketing to Get More Leads and Customers with HyperGro...
Deep Dive: AI-Powered Marketing to Get More Leads and Customers with HyperGro...
 
Freshworks Rethinks NoSQL for Rapid Scaling & Cost-Efficiency
Freshworks Rethinks NoSQL for Rapid Scaling & Cost-EfficiencyFreshworks Rethinks NoSQL for Rapid Scaling & Cost-Efficiency
Freshworks Rethinks NoSQL for Rapid Scaling & Cost-Efficiency
 
"Choosing proper type of scaling", Olena Syrota
"Choosing proper type of scaling", Olena Syrota"Choosing proper type of scaling", Olena Syrota
"Choosing proper type of scaling", Olena Syrota
 
Fueling AI with Great Data with Airbyte Webinar
Fueling AI with Great Data with Airbyte WebinarFueling AI with Great Data with Airbyte Webinar
Fueling AI with Great Data with Airbyte Webinar
 
HCL Notes and Domino License Cost Reduction in the World of DLAU
HCL Notes and Domino License Cost Reduction in the World of DLAUHCL Notes and Domino License Cost Reduction in the World of DLAU
HCL Notes and Domino License Cost Reduction in the World of DLAU
 
Essentials of Automations: Exploring Attributes & Automation Parameters
Essentials of Automations: Exploring Attributes & Automation ParametersEssentials of Automations: Exploring Attributes & Automation Parameters
Essentials of Automations: Exploring Attributes & Automation Parameters
 
Programming Foundation Models with DSPy - Meetup Slides
Programming Foundation Models with DSPy - Meetup SlidesProgramming Foundation Models with DSPy - Meetup Slides
Programming Foundation Models with DSPy - Meetup Slides
 
GNSS spoofing via SDR (Criptored Talks 2024)
GNSS spoofing via SDR (Criptored Talks 2024)GNSS spoofing via SDR (Criptored Talks 2024)
GNSS spoofing via SDR (Criptored Talks 2024)
 
Leveraging the Graph for Clinical Trials and Standards
Leveraging the Graph for Clinical Trials and StandardsLeveraging the Graph for Clinical Trials and Standards
Leveraging the Graph for Clinical Trials and Standards
 
Y-Combinator seed pitch deck template PP
Y-Combinator seed pitch deck template PPY-Combinator seed pitch deck template PP
Y-Combinator seed pitch deck template PP
 
AppSec PNW: Android and iOS Application Security with MobSF
AppSec PNW: Android and iOS Application Security with MobSFAppSec PNW: Android and iOS Application Security with MobSF
AppSec PNW: Android and iOS Application Security with MobSF
 
5th LF Energy Power Grid Model Meet-up Slides
5th LF Energy Power Grid Model Meet-up Slides5th LF Energy Power Grid Model Meet-up Slides
5th LF Energy Power Grid Model Meet-up Slides
 
Mutation Testing for Task-Oriented Chatbots
Mutation Testing for Task-Oriented ChatbotsMutation Testing for Task-Oriented Chatbots
Mutation Testing for Task-Oriented Chatbots
 
Energy Efficient Video Encoding for Cloud and Edge Computing Instances
Energy Efficient Video Encoding for Cloud and Edge Computing InstancesEnergy Efficient Video Encoding for Cloud and Edge Computing Instances
Energy Efficient Video Encoding for Cloud and Edge Computing Instances
 
JavaLand 2024: Application Development Green Masterplan
JavaLand 2024: Application Development Green MasterplanJavaLand 2024: Application Development Green Masterplan
JavaLand 2024: Application Development Green Masterplan
 
Harnessing the Power of NLP and Knowledge Graphs for Opioid Research
Harnessing the Power of NLP and Knowledge Graphs for Opioid ResearchHarnessing the Power of NLP and Knowledge Graphs for Opioid Research
Harnessing the Power of NLP and Knowledge Graphs for Opioid Research
 
"Frontline Battles with DDoS: Best practices and Lessons Learned", Igor Ivaniuk
"Frontline Battles with DDoS: Best practices and Lessons Learned",  Igor Ivaniuk"Frontline Battles with DDoS: Best practices and Lessons Learned",  Igor Ivaniuk
"Frontline Battles with DDoS: Best practices and Lessons Learned", Igor Ivaniuk
 

Una Critica a Rails by Luca Guidi

  • 1. March 22nd, 2013 A Rails Criticism how i learned to stop worrying about the Golden Path Luca Guidi
  • 3. Luca Guidi Senior Developer at Litmus @jodosha - http//lucag uidi.com
  • 4. litmus Beautiful Email previews Campaig n analytics Spam filter tests HTML code analysis And many other..
  • 5. Why Rails has revolutionized web development? (IMHO)
  • 6. Why Rails has revolutionized web development? Convention Over Config uration (IMHO) :)
  • 7. Why Rails has revolutionized web development? Dynamic and innovative Convention Over Config uration ecosystem (IMHO) :)
  • 8. Why Rails has revolutionized web development? Dynamic and innovative Convention Over Productivity and Developer uration Config Happiness ecosystem (IMHO) :)
  • 9. ..but The Framework is almost ten years old
  • 10. ..but TheLot of Legacy Code A Framework is almost ten years old is around
  • 11. ..but TheLot of Legacymajor A Frameworkais Code Upgrades to almost release years old ten are *painful* is around
  • 12. AGENDA intro problems
  • 14. Active Record Models != Records
  • 15. Active Record Encapsulation violations 1 if article.statearticle.published? 1 unless != 'published' 2 article.update_attribute(state: 'published') 2 article.publish! 3 end 3 end 4 # not completely right...
  • 16. Active Record Encapsulation violations 1 if article.statearticle.published? 1 unless != 'published' 2 article.update_attribute(state: 'published') 2 article.publish! 3 end 3 end 4 # not completely right...
  • 17. Active Record Encapsulation violations 1 if article.statearticle.published? 1 unless != 'published' 2 article.update_attribute(state: 'published') 2 article.publish! 3 end 3 end 4 # not completely right...
  • 18. Active Record Tell, Don’t Ask 1 2 violations article.publish! unless article.published? # article.publish! push the implementation 3 end # into the model 4 # not completely right...
  • 19. Active Record Tell, Don’t Ask violations 1 article.publish! unless article.published? 2 # article.publish! push the implementation 3 end # into the model 4 # not completely right...
  • 20. Active Record Tell, Don’t Ask violations 1 article.publish! unless article.published? 2 # article.publish! push the implementation 3 end # into the model 4 # not completely right...
  • 21. Active Record 2 Implicit vs Explicit API 1 class Post < ActiveRecord::Base 1 Post.where(state:'published'). 1 Post.most_recent_published def self.most_recent_published(limit = 5) 3 2published.recent(limit).order('created_at DESC') order('created_at DESC'). 4 end 5 3 limit(5) 6 private 7 scope :published, ->() { where(state: 'published') } 8 scope :recent, ->(n) { limit(n) } 9 end
  • 22. Active Record Implicit vs Explicit API 1 class Post < ActiveRecord::Base 2 1 Post.where(state:'published'). 1 Post.most_recent_published def self.most_recent_published(limit = 5) 3 2published.recent(limit).order('created_at DESC') order('created_at DESC'). 4 end 5 3 limit(5) 6 private 7 scope :published, ->() { where(state: 'published') } 8 scope :recent, ->(n) { limit(n) } 9 end
  • 23. Active Record Implicit vs Explicit API 1 class Post < ActiveRecord::Base 2 1 Post.where(state:'published'). 1 Post.most_recent_published def self.most_recent_published(limit = 5) 3 2published.recent(limit).order('created_at DESC') order('created_at DESC'). 4 end 5 3 limit(5) 6 private 7 scope :published, ->() { where(state: 'published') } 8 scope :recent, ->(n) { limit(n) } 9 end
  • 24. Active Record Implicit vs Explicit API 1 class Post < ActiveRecord::Base 2 1 Post.where(state:'published'). 1 Post.most_recent_published def self.most_recent_published(limit = 5) 3 2published.recent(limit).order('created_at DESC') order('created_at DESC'). 4 end 5 3 limit(5) 6 private 7 scope :published, ->() { where(state: 'published') } 8 scope :recent, ->(n) { limit(n) } 9 end
  • 25. Active Record Callbacks abuse Non-persistence logic is tight to the persistence life cycle. Eg. Sending emails
  • 26. Active Record Testability issues Micheal Feathers
  • 27. Active Record A test is not a unit test if it talks Testability issues to a database. Micheal Feathers
  • 28. Action Controller Action Controller It doesn’t affect too much your architecture, but it has strange OOP design.
  • 29. Action Controller 1 class PostsController < ApplicationController 2 before_filter :authenticate Frankenstein Controllers 3 4 def new 5 end 6 7 def create 8 @post = Post.new(params[:post]) 9 10 if @post.save 11 redirect_to post_url(@post), notice: 'Yay!' 12 else 13 render :new 14 end 15 end 16 end
  • 30. Action Controller Frankenstein Controllers 1 class PostsController < ApplicationController 2 before_filter :authenticate 3 4 def new 5 end 6 7 def create 8 @post = Post.new(params[:post]) 9 10 if @post.save 11 redirect_to post_url(@post), notice: 'Yay!' 12 else 13 render :new 14 end 15 end 16 end
  • 31. Action Controller Frankenstein Controllers 1 class PostsController < ApplicationController 2 before_filter :authenticate 3 4 def new 5 end 6 7 def create 8 @post = Post.new(params[:post]) 9 10 if @post.save 11 redirect_to post_url(@post), notice: 'Yay!' 12 else 13 render :new 14 end 15 end 16 end
  • 32. Action Controller Frankenstein Controllers 1 class PostsController < ApplicationController 2 before_filter :authenticate 3 4 def new 5 end 6 7 def create 8 @post = Post.new(params[:post]) 9 10 if @post.save 11 redirect_to post_url(@post), notice: 'Yay!' 12 else 13 render :new 14 end 15 end 16 end
  • 33. Action Controller Frankenstein Controllers 1 class PostsController < ApplicationController 2 before_filter :authenticate 3 4 def new 5 end 6 7 def create 8 @post = Post.new(params[:post]) 9 10 if @post.save 11 redirect_to post_url(@post), notice: 'Yay!' 12 else 13 render :new 14 end 15 end 16 end
  • 34. Action Controller Frankenstein Controllers 1 class PostsController < ApplicationController 2 before_filter :authenticate 3 4 def new 5 end 6 7 def create 8 @post = Post.new(params[:post]) 9 10 if @post.save 11 redirect_to post_url(@post), notice: 'Yay!' 12 else 13 render :new 14 end 15 end 16 end
  • 35. Action Controller 1 class PostsController < ApplicationController 2 # ... Odd classes 3 4 def create 5 @post = Post.new(params[:post]) 6 7 if @post.save 8 # ... 9 else 10 # ... 11 end 12 end 13 end
  • 36. Action Controller Odd classes 1 class PostsController < ApplicationController 2 # ... 3 4 def create 5 @post = Post.new(params[:post]) 6 7 if @post.save 8 # ... 9 else 10 # ... 11 end 12 end 13 end
  • 37. Action Controller Odd classes 1 class PostsController < ApplicationController 2 # ... 3 4 def create 5 @post = Post.new(params[:post]) 6 7 if @post.save 8 # ... 9 else 10 # ... 11 end 12 end 13 end
  • 38. Action Controller Odd classes 1 class PostsController < ApplicationController 2 # ... 3 4 def create 5 @post = Post.new(params[:post]) 6 7 if @post.save 8 # ... 9 else 10 # ... 11 end 12 end 13 end
  • 39. Action Controller 3 4 Encapsulation violations 1 class PostsController < ApplicationController 2 # ... def create 5 @post = Post.new(params[:post]) 6 # ... 7 end 8 end
  • 40. Action Controller Encapsulation violations 1 class PostsController < ApplicationController 2 # ... 3 4 def create 5 @post = Post.new(params[:post]) 6 # ... 7 end 8 end
  • 41. Action Controller 1 describe PostsController do Testability issues 2 it 'assigns @posts' do 3 Post.should_receive(:most_recent_published). 4 and_return(posts = [mock]) 5 get :index 6 7 expect(assigns(:posts)).to eq(posts) 8 end 9 end
  • 42. Action Controller Testability issues 1 describe PostsController do 2 it 'assigns @posts' do 3 Post.should_receive(:most_recent_published). 4 and_return(posts = [mock]) 5 get :index 6 7 expect(assigns(:posts)).to eq(posts) 8 end 9 end
  • 43. Action Controller Testability issues 1 describe PostsController do 2 it 'assigns @posts' do 3 Post.should_receive(:most_recent_published). 4 and_return(posts = [mock]) 5 get :index 6 7 expect(assigns(:posts)).to eq(posts) 8 end 9 end
  • 44. Action Controller Testability issues 1 describe PostsController do 2 it 'assigns @posts' do 3 Post.should_receive(:most_recent_published). 4 and_return(posts = [mock]) 5 get :index 6 7 expect(assigns(:posts)).to eq(posts) 8 end 9 end
  • 45. Action Controller Testability issues 1 describe PostsController do 2 it 'assigns @posts' do 3 Post.should_receive(:most_recent_published). 4 and_return(posts = [mock]) 5 get :index 6 7 expect(assigns(:posts)).to eq(posts) 8 end 9 end
  • 46. Action Controller Testability issues 1 describe PostsController do 2 it 'assigns @posts' do 3 Post.should_receive(:most_recent_published). 4 and_return(posts = [mock]) 5 get :index 6 7 expect(assigns(:posts)).to eq(posts) 8 end 9 end
  • 48. Action View Views aren’t views (but templates with logic) Without “real” views (or In an ideal world we presenters), we’re tempted to shouldn’t test our push presentational methods templates. into the models.
  • 49. Action View Helpers are functional programming 1 def user_full_name(user) 2 [ user.first_name, user.last_name ].join(' ') 3 end 4 5 url_for 6 # vs Half-assed way to solve 7 Url.for presentational problems in 8 ActionView. 9 posts_url
  • 50. Action View Helpers are functional programming 1 def user_full_name(user) 2 [ user.first_name, user.last_name ].join(' ') 3 end 4 5 url_for 6 # vs Half-assed way to solve 7 Url.for presentational problems in 8 ActionView. 9 posts_url
  • 51. Ruby on Rails Ruby on Rails
  • 52. Ruby on Rails Rails isn’t a framework, but an application template
  • 53. Ruby on Rails Rails is multi-paradig m as Ruby is.
  • 54. AGENDA intro problems solutions
  • 55. Solutions Decouple your logic from ActiveRecord as much as possible. AR is focused on data, but OOP is about behavior.
  • 56. Solutions Don’t think in ActiveRecord terms. Database is a detail, forget about associations, scopes, validations..
  • 57. Solutions Let your public API to declare intents. Let your design to emerge via TDD.
  • 58. Solutions Keep methods and accessors private as much as possible. Public APIs are hard to maintain as the codebase and the team grows.
  • 59. Solutions Skinny controllers and skinny models. Use ser vice objects or DCI, they are easier and faster to test.
  • 60. Solutions Don’t be afraid to extract ad-hoc classes for specific responsibilities. Inner classes are your friends, they help you with details, and aren’t part of your public API.
  • 61. Solutions Use DIY presenters They will help you to keep your models clean from presentational logic.
  • 63. AGENDA intro problems solutions conclusion
  • 64. Q&A
  • 65. me@lucag uidi.com @jodosha https://speakerdeck.com/jodosha/a-rails-criticism Except where otherwise noted, this work is licensed under: http://creativecommons.org/licenses/by-nc-sa/3.0/