Upgrade to Pro — share decks privately, control downloads, hide ads and more …

RubyConf Brasil 2011

RubyConf Brasil 2011

Uma breve compilação de todas as apresentações do RubyConf Brasil 2011

Fabiano Almeida

October 21, 2011
Tweet

More Decks by Fabiano Almeida

Other Decks in Programming

Transcript

  1. Ruby é fácil? Fácil para fazer coisas simples É mais

    difícil do que realmente é Conhecer seu princípio é a base da facilidade Aprender uma nova linguagem pode ser fácil Porém, sempre existirá uma curva de aprendizado David Black @david_a_black 2 quarta-feira, 23 de novembro de 11
  2. Surpresas no uso de concorrência em Rails class User <

    ActiveRecord::Base validades_uniqueness_of :email end Rails não garante unicidade Marcos Toledo @mtoledo ⤷ Unicidade 4 quarta-feira, 23 de novembro de 11
  3. Surpresas no uso de concorrência em Rails class AddUniquenessIndexToUserEmail <

    ActiveRecord::Migration def self.up add_index :users, :email, :unique => true end def self.down remove_index :users, :email end end Marcos Toledo @mtoledo ⤷ Solução 5 quarta-feira, 23 de novembro de 11
  4. class Comment < ActiveRecord::Base belongs_to :post validates_presence_of :post end class

    Post < ActiveRecord::Base has_many :comments, :dependent => :destroy end Surpresas no uso de concorrência em Rails Rails não garante dependência entre eles Marcos Toledo @mtoledo ⤷ Dependência de registros 6 quarta-feira, 23 de novembro de 11
  5. Surpresas no uso de concorrência em Rails create_table :comments do

    |table| table.integer :post_id, :null => false end ActiveRecord::Base.connection.execute <<-EOS ALTER TABLE ‘comments’ ADD CONSTRAINT FOREIGN KEY (post_id) REFERENCES posts(id) ON DELETE restrict ON UPDATE cascade EOS Marcos Toledo @mtoledo ⤷ Solução 7 quarta-feira, 23 de novembro de 11
  6. class Comment < ActiveRecord::Base after_create :update_posts_count def update_posts_count self.posts.increment :comments_count

    end end class Post < ActiveRecord::Base after_update :update_comments def update_comments comments.each { |c| c.published = self.published; c.save } end end Surpresas no uso de concorrência em Rails Transações lock tabelas na atualização Marcos Toledo @mtoledo ⤷ Deadlock 8 quarta-feira, 23 de novembro de 11
  7. Surpresas no uso de concorrência em Rails Marcos Toledo @mtoledo

    ⤷ Deadlock 9 quarta-feira, 23 de novembro de 11
  8. Surpresas no uso de concorrência em Rails Marcos Toledo @mtoledo

    ⤷ Solução #1 => Atualizar dependentes antes class Comment < ActiveRecord::Base after_create :update_posts_count def update_posts_count self.posts.increment :comments_count end end class Post < ActiveRecord::Base before_update :update_comments def update_comments comments.each { |c| c.published = self.published; c.save } end end 10 quarta-feira, 23 de novembro de 11
  9. Surpresas no uso de concorrência em Rails Marcos Toledo @mtoledo

    ⤷ Solução #1 => Atualizar dependentes antes class Comment < ActiveRecord::Base after_create :update_posts_count def update_posts_count self.posts.increment :comments_count end end class Post < ActiveRecord::Base before_update :update_comments def update_comments comments.each { |c| c.published = self.published; c.save } end end 11 quarta-feira, 23 de novembro de 11
  10. Surpresas no uso de concorrência em Rails Marcos Toledo @mtoledo

    ⤷ Solução #2 => Evite propagação de estado class Comment < ActiveRecord::Base def visible? post.published? && self.published? end end 12 quarta-feira, 23 de novembro de 11
  11. Hypermedia: O ingrediente perdido do REST REST => Representational State

    Transfer REST utiliza características do HTTP Usamos pouco do REST Roar => framework dele para trabalhar com REST Facilitador na troca de mensagens e estado Passagem de links personalizados via REST Nick Sutterer @apotonick 15 quarta-feira, 23 de novembro de 11
  12. Hypermedia: O ingrediente perdido do REST class Beer < ActiveRecord::Base

    include Roar::Representer::JSON # should be XML, for example property :name # plain property property :id # plain property link :self do beer_url(id) # Hypermedia support end end Nick Sutterer @apotonick ⤷ Roar: exemplo 16 quarta-feira, 23 de novembro de 11
  13. Hypermedia: O ingrediente perdido do REST brew = Beer.new( :id

    => 1, :name => “NickBrew” ).to_json # from Roar { “beer”:{ “id” : 1, “name” : “NickBrew”, “links” : [{ “rel” : “self”, “href” : “http://beers/1” }] } } brew.links[:self] #=> “http://beers/1” Nick Sutterer @apotonick ⤷ Roar: exemplo 17 quarta-feira, 23 de novembro de 11
  14. Hypermedia: O ingrediente perdido do REST brew = Beer.from_json ‘{

    “beer”:{ “id” : 1, “name” : “NickBrew” } }’ brew.name #=> “NickBrew” Nick Sutterer @apotonick ⤷ Roar: exemplo 18 quarta-feira, 23 de novembro de 11
  15. SOLID através de BDD: Guia prático para Rubistas Criador Robert

    “Uncle Bob” Martin @unclebobmartin SOLID S: Single responsibility O: Open-closed L: Liskov substitution I: Interface segregation D: Dependency inversion Lucas Húngaro @lucashungaro S: deve ter apenas uma única responsabilidade O: entidades deveriam ser abertas por extensão, mas fechada por modificação L: objetos deveriam ser sobrescritos com instâncias de seus sub-tipos sem alterar o correto funcionamento do sistema I: muitas interfaces específicas de clientes são melhores que uma interface de propósito generalizado D: crie dependências por abstrações, não por classes concretas 20 quarta-feira, 23 de novembro de 11
  16. SOLID através de BDD: Guia prático para Rubistas Rails =>

    codificação rápida Menos atenção a aspectos importantes Fat Models aka programação procedural Solução: OOP, BDD, SOLID SRP => Single Responsibility DIP => Dependency Inversion Coesão e acoplamento Lucas Húngaro @lucashungaro 21 quarta-feira, 23 de novembro de 11
  17. SOLID através de BDD: Guia prático para Rubistas Eliminar a

    baixa coesão Executa parte de uma ou mais responsabilidades Eliminar o alto acoplamento Um caso de uso e suas dependências Apps padrão (migrations, finders): Models gigantes (fat models) Classes sem importância Lucas Húngaro @lucashungaro 22 quarta-feira, 23 de novembro de 11
  18. SOLID através de BDD: Guia prático para Rubistas Models com

    responsabilidades bem definidas Evitar ter testes que dependam de BDs Fortalecer a utilização dos Mocks Escrever testes isolados para AR é difícil ActiveRecord: validações, associações e finders SOMENTE! Quer mudar? Comece pelo comportamento! Lucas Húngaro @lucashungaro 23 quarta-feira, 23 de novembro de 11
  19. class User < ActiveRecord::Base attr_accessible :email, :password validates :password, :on

    => :create has_secure_password def send_password_reset generate_token(:password_reset_token) self.password_reset_sent_at = Time.zone.now save! UserMailer.password_reset(self).deliver end def generate_token begin self[column] = SecureRandom.urlsafe_base64 end while User.exists? (column => self[column]) end end ⤷ Exemplo: Fat model Lucas Húngaro @lucashungaro SOLID através de BDD: Guia prático para Rubistas 24 quarta-feira, 23 de novembro de 11
  20. class User < ActiveRecord::Base attr_accessible :email, :password validates :password, :on

    => :create has_secure_password def send_password_reset generate_token(:password_reset_token) self.password_reset_sent_at = Time.zone.now save! UserMailer.password_reset(self).deliver end def generate_token begin self[column] = SecureRandom.urlsafe_base64 end while User.exists? (column => self[column]) end end ⤷ Exemplo: Fat model Lucas Húngaro @lucashungaro SOLID através de BDD: Guia prático para Rubistas 25 quarta-feira, 23 de novembro de 11
  21. ⤷ Sugestão: Teste Lucas Húngaro @lucashungaro SOLID através de BDD:

    Guia prático para Rubistas describe UserAuthentication do let(:user) { Factory(:user) } let(:password) { “123456” } context “with valid credentials” do subject{ UserAuthentication.new( user.username, password ) } it “allow access” do subject.authenticate.should be_true end end context “with invalid credentials” do subject{ UserAuthentication.new( user.username, “invalid” ) } it “denied access” do subject.authenticate.should be_true end end end 26 quarta-feira, 23 de novembro de 11
  22. ⤷ Sugestão: Model Lucas Húngaro @lucashungaro SOLID através de BDD:

    Guia prático para Rubistas class UserAuthentication def initialize(username, password) @username= username @password= password end def authenticate if user = User.find_by_username(@username) user.password_hash == BCrypt::Engine.hash_secret(@password, user.password_salt) else false end end end Acoplamento 27 quarta-feira, 23 de novembro de 11
  23. Mas, como melhorar isso? Lucas Húngaro @lucashungaro SOLID através de

    BDD: Guia prático para Rubistas ⤷ Objetos dublês ⤷ Injeção de dependência Consigo garantir ⤷ Objetos desacoplados e coesos ⤷ Testes rápidos ⤷ Custo de manutenção reduzido 28 quarta-feira, 23 de novembro de 11
  24. ⤷ Certo, beleza. E como ficaria? Lucas Húngaro @lucashungaro SOLID

    através de BDD: Guia prático para Rubistas class UserAuthentication def initialize(username, password) @username= username @password= password end def authenticate(user_repo = User, encryption_engine = BCrypt::Engine) if user = user_repo.find_by_username(@username) user.password_hash == encryption_engine.hash_secret(@password, user.password_salt) else false end end end 29 quarta-feira, 23 de novembro de 11
  25. ⤷ Certo, beleza. E como ficaria? # Teste Lucas Húngaro

    @lucashungaro SOLID através de BDD: Guia prático para Rubistas describe UserAuthentication do let(:user) { double(“an user”).as_null_object } let(:user_repo) { double(“an user repository”) } let(:encryption_engine) { double(“an encryption engine”) } before(:each) do user.stub(:password_hash).and_return “the hash” user_repo.stub(:find_by_username).and_return user end context “with valid credentials” do before(:each) { encryption_engine.stub( :hash_secret ).and_return user.password_hash } subject{ UserAuthentication.new( “username”, “123456” ) } it “allow access” do subject.authenticate(user_repo, encryption_engine).should be_true end end context “with invalid credentials” do before(:each) { encryption_engine.stub( :hash_secret ).and_return “another hash” } subject{ UserAuthentication.new( “username”, “invalid” ) } it “denied access” do subject.authenticate(user_repo, encryption_engine).should be_true end end end 30 quarta-feira, 23 de novembro de 11
  26. Aplicação RoR sem recarga de página Próxima geração Gmail, Twitter,

    Facebook, GitHub, Foursquare etc. Single Page Applications Spine.js - Backbone.js melhorado! MVC em JavaScript Fortemente baseado em requisições AJAX Aplicação simples, limpa e iterativa Roberto Rodriguez Artavia @rodriguezartav 32 quarta-feira, 23 de novembro de 11
  27. Aplicação RoR sem recarga de página Roberto Rodriguez Artavia @rodriguezartav

    ⤷ Aplicação Web Tradicional 33 quarta-feira, 23 de novembro de 11
  28. Aplicação RoR sem recarga de página Roberto Rodriguez Artavia @rodriguezartav

    ⤷ Aplicação Web Tradicional com AJAX 34 quarta-feira, 23 de novembro de 11
  29. Aplicação RoR sem recarga de página Roberto Rodriguez Artavia @rodriguezartav

    ⤷ Aplicação Web de Página Única 35 quarta-feira, 23 de novembro de 11
  30. Aplicação RoR sem recarga de página Roberto Rodriguez Artavia @rodriguezartav

    ⤷ Spine Model class Page extends Spine.Model @configure “Page”, “name”, “slug”, “body”, “count” window.Page = Page Create(), Save(), Destroy() page = Page.create {name: “One page”, slug: “Slug” ...} fetch(), find(), all(), last(), findAllByAttribute() pages = Page.all() 36 quarta-feira, 23 de novembro de 11
  31. Aplicação RoR sem recarga de página Roberto Rodriguez Artavia @rodriguezartav

    ⤷ Spine Controller class PagesList extends Spine.Controller className: “list” elements: “.items” : “items” # var items = $(‘.items’) events: “click .item” : “show” # $(‘.item’).bind(‘click’, ...) “click .create” : “create” “click span.button” : “destroy” constructos: -> super @el.html $.tmpl(“app/views/pages/list”) # Template @refreshElements() Page.bind(“refresh change”, @render) # Model Event Binding <h1>Pages</h1> <ul class=”items”></ul> <a class=”create”>Create Page</a> 37 quarta-feira, 23 de novembro de 11
  32. Aplicação RoR sem recarga de página Roberto Rodriguez Artavia @rodriguezartav

    ⤷ Spine Controller class PagesEdit extends Spine.Controller ... class PagesList extends Spine.Controller ... class Pages extends Spine.Controller elements: “#list” : “list_view” “#edit” : “edit_view” constructos: -> super @list = new PagesList(el: @list_view) @edit = new PagesEdit(el: @list_edit) @routes “/pages” : (params) => @el.removeClass(‘show_edit’) “/pages/:id/edit” : (params) => @edit.active(params) @el.addClass(‘show_edit’) Page.fetch() window.Pages = Pages 38 quarta-feira, 23 de novembro de 11
  33. Quem faz o melhor churrasco? Melhora na gestão de conexões

    ativas Antes: cada model criava um novo pool Gerenciamento de rotas Fazer o match de uma rota: if pra todo canto E se tivermos muitas rotas? Muito, muito lento! Fundamento: autômatos e expressão regular Muito mais rápido Aaron Patterson @tenderlove 40 quarta-feira, 23 de novembro de 11
  34. Quem faz o melhor churrasco? Rails Routes resource :articles /articles(.:format)

    /articles/new(.:format) /articles/:id/edit(.:format) /articles/:id(.:format) Aaron Patterson @tenderlove 41 quarta-feira, 23 de novembro de 11
  35. Quem faz o melhor churrasco? Aaron Patterson @tenderlove GET /articles/new

    /articles(.:format) /articles/new(.:format) /articles/:id/edit(.:format) /articles/:id(.:format) 42 quarta-feira, 23 de novembro de 11
  36. Quem faz o melhor churrasco? Aaron Patterson @tenderlove GET /articles/new

    /articles(.:format) /articles/new(.:format) /articles/:id/edit(.:format) /articles/:id(.:format) 43 quarta-feira, 23 de novembro de 11
  37. Quem faz o melhor churrasco? Aaron Patterson @tenderlove GET /articles/new

    /articles(.:format) /articles/new(.:format) /articles/:id/edit(.:format) /articles/:id(.:format) 200 OK! 44 quarta-feira, 23 de novembro de 11
  38. Quem faz o melhor churrasco? Aaron Patterson @tenderlove GET /foos/new

    /articles(.:format) /articles/new(.:format) /articles/:id/edit(.:format) /articles/:id(.:format) 45 quarta-feira, 23 de novembro de 11
  39. Quem faz o melhor churrasco? Aaron Patterson @tenderlove GET /foos/new

    /articles(.:format) /articles/new(.:format) /articles/:id/edit(.:format) /articles/:id(.:format) 46 quarta-feira, 23 de novembro de 11
  40. Quem faz o melhor churrasco? Aaron Patterson @tenderlove GET /foos/new

    /articles(.:format) /articles/new(.:format) /articles/:id/edit(.:format) /articles/:id(.:format) 47 quarta-feira, 23 de novembro de 11
  41. Quem faz o melhor churrasco? Aaron Patterson @tenderlove GET /foos/new

    /articles(.:format) /articles/new(.:format) /articles/:id/edit(.:format) /articles/:id(.:format) 48 quarta-feira, 23 de novembro de 11
  42. Quem faz o melhor churrasco? Aaron Patterson @tenderlove GET /foos/new

    /articles(.:format) /articles/new(.:format) /articles/:id/edit(.:format) /articles/:id(.:format) 404 Not Found 49 quarta-feira, 23 de novembro de 11
  43. Quem faz o melhor churrasco? Quanto tempo isso leva? r

    = routes.length rg = regexp compare O( r * rg ) Isso leva muito tempo! Pode ser melhorado? Claro, autômatos Aaron Patterson @tenderlove 50 quarta-feira, 23 de novembro de 11
  44. Quem faz o melhor churrasco? Aaron Patterson @tenderlove ⤷ resource

    :users 51 quarta-feira, 23 de novembro de 11
  45. Rails Views: Codificando sua interface como um profissi... Views sujas

    e de difícil manutenção Utilização de gems que fazem coisas triviais Dispatch JS; Simple Form; Simple Presenter Aprenda a usar partials Não utilizar CoffeeScript - difícil de depurar Usar o charset na aplicação <meta charset=”utf-8”/> Use locale: <html dir=”ltr” lang=”<%= I18n.locale %>”> Nando Vieira @fnando 55 quarta-feira, 23 de novembro de 11
  46. Aprenda mais sobre Ruby criando sua própria linguagem Rails Core

    Team Elixir “extends” Erlang Aprendeu ainda mais sobre Ruby E se não existissem blocos? E se existisse Arrays e Hashes comprehensions? E se existisse interfaces? E partial applications? Aprendam novas linguagens José Valim @josevalim 57 quarta-feira, 23 de novembro de 11
  47. Código melhor através de Design de interface Design de interfaces

    é importante Designer presente na construção do projeto Todas as etapas Programador entende / analisa requisitos Designer entende / analisa views Identifica melhorias na apresentação das informações Daniel Lopes @danielvlopes 60 quarta-feira, 23 de novembro de 11
  48. Recapitulando Conheça os princípios da linguagem O BD deve SEMPRE

    garantir a integridade dos dados Use REST como realmente deve ser: simples! Use SOLID, você não morrerá por fazer da forma certa Se puder, evite refreshes em tela; Use Single Page Applications Crie desapego pelo seu código... Refactore ele! Lógica de programação não deve estar nas views Aprenda novas linguagens, você ganhará muito mais Um bom design é fundamental 77 quarta-feira, 23 de novembro de 11