$30 off During Our Annual Pro Sale. View Details »

Poderosas Interfaces Rails

Poderosas Interfaces Rails

Esta palestra aborda boas práticas na modelagem de aplicações Rails. São apresentadas algumas técnicas que auxiliam na criação de componentes de baixo acoplamento, facilitando o desenvolvimento e manutenção destes componentes, diminuindo o tempo de execução de seus testes unitários e proporcionando uma experiência mais prazerosa no desenvolvimento de aplicações complexas utilizando Ruby e Rails.

Carlos Souza

August 30, 2012
Tweet

More Decks by Carlos Souza

Other Decks in Technology

Transcript

  1. Poderosas Interfaces
    Rails
    Caike Souza
    RubyConf BR 2012

    View Slide

  2. @caike

    View Slide

  3. View Slide

  4. View Slide

  5. View Slide

  6. View Slide

  7. Problemas
    http://www.flickr.com/photos/lianneviau/499003712/sizes/l/in/photostream/

    View Slide

  8. class PaymentsController < ApplicationController
    def create
    payment = Payment.new(params[:payment])
    if payment.save
    redirect_to(payment, success:'You are now subscribed!')
    else
    render :index
    end
    end
    end

    View Slide

  9. class PaymentsController < ApplicationController
    def create
    payment = Payment.new(params[:payment])
    if payment.save
    redirect_to(payment, success:'You are now subscribed!')
    else
    render :index
    end
    end
    end
    Client

    View Slide

  10. class PaymentsController < ApplicationController
    def create
    payment = Payment.new(params[:payment])
    if payment.save
    redirect_to(payment, success:'You are now subscribed!')
    else
    render :index
    end
    end
    end
    Client
    Interface

    View Slide

  11. Interface

    View Slide

  12. class PaymentsController < ApplicationController
    def create
    payment = Payment.new(params[:payment])
    if payment.save
    redirect_to(payment, success:'You are now subscribed!')
    else
    render :index
    end
    end
    end
    Client

    View Slide

  13. class PaymentsController < ApplicationController
    def create
    payment = Payment.new(params[:payment])
    if payment.save
    redirect_to(payment, success:'You are now subscribed!')
    else
    render :index
    end
    end
    end

    View Slide

  14. class PaymentsController < ApplicationController
    def create
    payment = Payment.new(params[:payment])
    if payment.save
    redirect_to(payment, success:'You are now subscribed!')
    else
    render :index
    end
    end
    end

    View Slide

  15. Protocolo

    View Slide

  16. class PaymentsController < ApplicationController
    def create
    payment = Payment.new(params[:payment])
    if payment.save
    redirect_to(payment, success:'You are now subscribed!')
    else
    render :index
    end
    end
    end

    View Slide

  17. class PaymentsController < ApplicationController
    def create
    payment = Payment.new(params[:payment])
    if payment.save
    redirect_to(payment,success: 'You are now subscribed!')
    else
    render :index
    end
    end
    end

    View Slide

  18. class PaymentsController < ApplicationController
    def create
    payment = Payment.new(params[:payment])
    if payment.save
    redirect_to(payment,success: 'You are now subscribed!')
    else
    render :index
    end
    end
    end
    Baixa Granularidade

    View Slide

  19. Granularidade

    View Slide

  20. class PaymentsController < ApplicationController
    def create
    payment = Payment.new(params[:payment])
    if payment.save
    redirect_to(payment,success: 'You are now subscribed!')
    else
    render :index
    end
    end
    end

    View Slide

  21. Callbacks
    &
    Observers
    if pra
    if ca
    if ralho
    e outras bizarrices

    View Slide

  22. As Três Leis das
    Interfaces

    View Slide

  23. Os Três Filtros de
    Interfaces

    View Slide

  24. fazer aquilo que
    seus métodos
    indicam fazer.
    #1

    View Slide

  25. class PaymentsController < ApplicationController
    def create
    payment = Payment.new(params[:payment])
    if payment.save
    redirect_to(payment, success:'You are now subscribed!')
    else
    render :index
    end
    end
    end

    View Slide

  26. class PaymentsController < ApplicationController
    def create
    payment = Payment.new(params[:payment])
    if payment.save
    redirect_to(payment, success:'You are now subscribed!')
    else
    render :index
    end
    end
    end

    View Slide

  27. Payment#save
    vs.
    Payment#place

    View Slide

  28. class PaymentsController < ApplicationController
    def create
    payment = Payment.new(params[:payment])
    if payment.save
    redirect_to(payment, success:'You are now subscribed!')
    else
    render :index
    end
    end
    end

    View Slide

  29. class PaymentsController < ApplicationController
    def create
    payment = Payment.new(params[:payment])
    if payment.place
    redirect_to(payment, success:'You are now subscribed!')
    else
    render :index
    end
    end
    end

    View Slide

  30. class Payment < ActiveRecord::Base
    protected :save
    ##
    # Add your comments here.
    # Really.
    ##
    def place
    end
    end

    View Slide

  31. deve ser
    eficiente.
    #2

    View Slide

  32. Usuários Registrados


    <% User.recent.paginate(@page).each do |user| %>
    <%= link_to(user.full_name, user) %>
    <% end %>


    View Slide

  33. Registered Users


    <% User.recent.paginate(@page).each do |user| %>
    <%= link_to(user.full_name, user) %>
    <% end %>


    View Slide

  34. Registered Users


    <% @users.each do |user| %>
    <%= link_to(user.full_name, user) %>
    <% end %>


    View Slide

  35. Usuários Registrados


    <% @users.each do |user| %>
    <%= link_to(user.full_name, user) %>
    <% end %>


    View Slide

  36. avisar ao client
    caso haja algum
    erro.
    #3

    View Slide

  37. raise "Invalid HTTP request"

    View Slide

  38. raise "Invalid HTTP request"

    View Slide

  39. raise "Invalid HTTP request"
    vs.
    raise "Erro na autorização do Cartão
    de Crédito"

    View Slide

  40. raise "Erro na autorização do Cartão
    de Crédito"

    View Slide

  41. raise "Erro na autorização do Cartão
    de Crédito"

    View Slide

  42. fazer aquilo que
    seus métodos
    indicam fazer.
    #1

    View Slide

  43. deve ser eficiente.
    #2

    View Slide

  44. avisar ao client
    caso haja algum
    erro.
    #3

    View Slide

  45. class PaymentsController < ApplicationController
    def create
    payment = Payment.new(params[:payment])
    if payment.save
    redirect_to(payment, success:'You are now subscribed!')
    else
    render :index
    end
    end
    end

    View Slide

  46. class PaymentsController < ApplicationController
    def create
    payment = Payment.new(params[:payment])
    if payment.save
    redirect_to(payment,success: 'You are now subscribed!')
    else
    render :index
    end
    end
    end

    View Slide

  47. class PaymentsController < ApplicationController
    def create
    payment = Payment.new(params[:payment])
    if payment.place
    redirect_to(payment,success: 'You are now subscribed!')
    else
    render :index
    end
    end
    end

    View Slide

  48. class PaymentsController < ApplicationController
    def create
    payment = Payment.new(params[:payment])
    if payment.place
    redirect_to(payment,success: 'You are now subscribed!')
    else
    render :index
    end
    end
    end
    fazendo muita coisa

    View Slide

  49. Factory Method

    View Slide

  50. class PaymentsController < ApplicationController
    def create
    payment = Payment.new(params[:payment])
    if payment.place
    redirect_to(payment,success: 'You are now subscribed!')
    else
    render :index
    end
    end
    end

    View Slide

  51. class PaymentsController < ApplicationController
    def create
    payment = Payment.build_with(params[:payment])
    if payment.place
    redirect_to(payment,success: 'You are now subscribed!')
    else
    render :index
    end
    end
    end

    View Slide

  52. class PaymentsController < ApplicationController
    def create
    payment = Payment.build_with(params[:payment])
    if payment.place
    redirect_to(payment, success:'You are now subscribed!')
    else
    render :index
    end
    end
    end

    View Slide

  53. class PaymentsController < ApplicationController
    def create
    payment = Payment.build_with(params[:payment])
    if payment.place
    redirect_to(payment, success:'You are now subscribed!')
    else
    render :index
    end
    end
    end

    View Slide

  54. class PaymentsController < ApplicationController
    def create
    payment = Payment.build_with(params[:payment])
    if payment.place
    redirect_to(payment, success:'You are now subscribed!')
    else
    render :index
    end
    end
    end

    View Slide

  55. class PlanSubscriber
    def self.build_for(user)
    end
    def subscribe(payment_info)
    end
    end

    View Slide

  56. class PlanSubscriber
    def self.build_for(user)
    end
    def subscribe(payment_info)
    end
    end

    View Slide

  57. require 'plan_subscriber'
    describe PlanSubscriber do
    end

    View Slide

  58. class PaymentsController < ApplicationController
    def create
    payment = Payment.build_with(params[:payment])
    if payment.place
    redirect_to(payment, success:'You are now subscribed!')
    else
    render :index
    end
    end
    end

    View Slide

  59. class PaymentsController < ApplicationController
    def create
    payment = Payment.build_with(params[:payment])
    if payment.place
    redirect_to(payment, success:'You are now subscribed!')
    else
    render :index
    end
    end
    end

    View Slide

  60. class PaymentsController < ApplicationController
    def create
    plan_subscriber = PlanSubscriber.build_for(current_user)
    if plan_subscriber.subscribe(params[:payment])
    payment = plan_subscriber.payment
    redirect_to(payment, success:'You are now subscribed!')
    else
    render :index
    end
    end
    end

    View Slide

  61. Models
    !=
    AR::Base

    View Slide

  62. Rails não é o seu
    domain
    http://blog.firsthand.ca/2011/10/rails-is-not-your-
    application.html

    View Slide

  63. View Slide

  64. Design by Contract

    View Slide

  65. Pre-Conditions
    Post-Conditions
    Invariants

    View Slide

  66. Pre-Conditions

    View Slide

  67. E-mail deve ser válido.
    Produto deve estar disponível.

    View Slide

  68. Pre-Conditions
    Post-Conditions

    View Slide

  69. Assento deve estar reservado.
    Novo pagamento deve ser criado.

    View Slide

  70. class PaymentsController < ApplicationController
    def create
    plan_subscriber = PlanSubscriber.build_for(current_user)
    if plan_subscriber.subscribe(params[:payment])
    payment = plan_subscriber.payment
    redirect_to(payment, success:'You are now subscribed!')
    else
    render :index
    end
    end
    end

    View Slide

  71. Pre-Conditions
    Post-Conditions
    Invariants

    View Slide

  72. Usuário deve estar ativado.
    Loja deve estar aberta.

    View Slide

  73. Pre-Conditions
    Post-Conditions
    Invariants

    View Slide

  74. View Slide

  75. Pirâmide de complexidade
    de models

    View Slide

  76. 0
    1
    2
    Pirâmide de complexidade
    de models

    View Slide

  77. 0
    Rails out-of-the-box
    1
    2
    Pirâmide de complexidade
    de models

    View Slide

  78. 0
    Rails out-of-the-box
    1
    Não utilizar métodos AR::Base
    nos controllers
    2
    Pirâmide de complexidade
    de models

    View Slide

  79. 0
    2
    Rails out-of-the-box
    Não utilizar classes AR::Base
    nos controllers
    1
    Não utilizar métodos AR::Base
    nos controllers
    Pirâmide de complexidade
    de models

    View Slide

  80. View Slide

  81. "Bons sistemas orientados a objeto
    focam em como as suas diferentes
    partes se comunicam, e não nas
    propriedades internas e
    comportamento dessas partes."
    Alan Kay

    View Slide

  82. Mensagens

    View Slide

  83. Mensagens

    View Slide

  84. Protocolo

    View Slide

  85. Os Três Filtros de
    Interfaces

    View Slide

  86. Design by Contract

    View Slide

  87. Obrigado :)

    View Slide

  88. Poderosas Interfaces
    Rails
    Caike Souza
    RubyConf BR 2012

    View Slide