boas práticas de design em aplicações ruby on rails

Post on 21-Jun-2015

642 Views

Category:

Technology

2 Downloads

Preview:

Click to see full reader

DESCRIPTION

5º Encontro Guru Sorocaba - Secot Ufscar

TRANSCRIPT

BOAS PRÁTICASDE DESIGN EMAPLICAÇÕES RAILSRINALDI FONSECArinaldifonseca.com@rinaldifonseca

sábado, 12 de maio de 12

sábado, 12 de maio de 12

UNCLE BOBMARTIN FOWLERSANDI METZE OUTROS

VAMOS CONSIDERAR PESSOAS COMO:

sábado, 12 de maio de 12

CLEAN CODEDESIGN PATTERNSSOLIDTODOS NÓS JÁ OUVIMOS FALAR

sábado, 12 de maio de 12

APLICAR NA PRÁTICAÉ DIFÍCIL

sábado, 12 de maio de 12

VAMOSPENSARNAESSÊNCIA

sábado, 12 de maio de 12

O DESIGN

sábado, 12 de maio de 12

O QUE É DESIGN??

sábado, 12 de maio de 12

O CÓDIGO

sábado, 12 de maio de 12

A ARTEDE ORGANIZARO CÓDIGO

sábado, 12 de maio de 12

CADA LINHACADA CLASSECADA TESTEFAZ PARTE DO DESIGN

sábado, 12 de maio de 12

E QUAL É O OBJETIVODO DESIGN?

sábado, 12 de maio de 12

REDUZIR O CUSTODA MUDANÇA

sábado, 12 de maio de 12

VAMOS PENSARQUE O CÓDIDODEVE FUNCIONAR HOJEE APENAS ISSO.

sábado, 12 de maio de 12

SER FÁCIL DE MUDARPARA SEMPRE.

DEVE

sábado, 12 de maio de 12

FIM DA PARTE 1

sábado, 12 de maio de 12

DICAS PRÁTICAS

sábado, 12 de maio de 12

AVISO:

O que vou falar, NÃO épapo de Javeiro =)

sábado, 12 de maio de 12

USAR CLASSES DE SERVIÇO

A.K.A. SERVICES

DICA 1

sábado, 12 de maio de 12

Rails e o MVC

sábado, 12 de maio de 12

FAT MODELSTHIN CONTROLLERS

sábado, 12 de maio de 12

DDD

DOMAIN DRIVEN DESIGN

ERIC EVANS

sábado, 12 de maio de 12

As vezes, lidamos com “coisas” que não se encaixam emdeterminados objetos

sábado, 12 de maio de 12

APPLICATION SERVICEDOMAIN SERVICEINFRASTRUCTURE SERVICE

sábado, 12 de maio de 12

Application Service

class AccountCSVExporter def self.to_csv(account) CSV.generate do |csv| account.transactions.each do |transaction| csv << [transaction.amount, transaction.created_on] end end endend

sábado, 12 de maio de 12

Domain Service

class FundsTransferService def self.transfer(from, to, amount) Account.transaction do from.debit amount to.credit amount end endend

sábado, 12 de maio de 12

Infrastructure Service

class MessagingService def self.overdrawn_account_sms(account) Rails.queue.push SmsJob, "#{account.number}!" endend

sábado, 12 de maio de 12

ENTITIES ANDVALUE OBJECTS

DICA 2

sábado, 12 de maio de 12

ENTITIES

Objetos identificáveis por suas identidades

São mutáveis(mantendo a identidade)

Possuem um ciclo de vida na aplicação

sábado, 12 de maio de 12

class Order < ActiveRecord::Base belongs_to :user has_one :addressend

class Address < ActiveRecord::Base belongs_to :orderend

sábado, 12 de maio de 12

VALUE OBJECTS

Objetos identificáveis por seu valores

São imutáveis

Descrevem “coisas”

sábado, 12 de maio de 12

class Address attr_reader :street, :city

def initialize(street, city) @street, @city = street, city end

end

sábado, 12 de maio de 12

class Order < ActiveRecord::Base belongs_to :user composed_of :address, :mapping => [%w(address_street street), %w(address_city city)]

end

sábado, 12 de maio de 12

PRESENTERS

DICA 3

sábado, 12 de maio de 12

*PRESENTERS*EXHIBTI OBJECTS

DECORATORSAttach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality. / Gang of Four

sábado, 12 de maio de 12

Lógica na View

<% if user_signed_in? %><%= product.name %><% else %><%= link_to product.name, product_path(product) %><% end %>

sábado, 12 de maio de 12

BasePresenter

require “delegate”class BasePresenter < SimpleDelegator attr_accessor :context

def initialize(model, context = nil, objects = []) objects.each do |key, value| self.class.send :define_method, key do value end end

@context = context super model endend

sábado, 12 de maio de 12

BasePresenter

class ProductPresenter < BasePresenter def display_name if user name else context.link_to name, context.product_path(self) end end

def display_description context.render “products/description”, :product => self endend

sábado, 12 de maio de 12

PresenterHelper

module PresenterHelper def present(presenter_class, model, objects) presenter = presenter_class.new(model, self, objects) yield presenter if block_given? presenter end

end

sábado, 12 de maio de 12

Utilização

<% present ProductPresenter, @product, :user => current_user do |presenter| %>

<%= presenter.display_name %> <%= presenter.display_description %>

<% end %>

sábado, 12 de maio de 12

ADAPTERS

DICA 4

sábado, 12 de maio de 12

ADAPTAR A INTERFACEDE UMA CLASSE

sábado, 12 de maio de 12

DEPENDÊNCIASEXTERNAS

GRANDES CHANCES DE MUDAR

sábado, 12 de maio de 12

Exemplo:

Gem Koalagithub.com/arsduo/koala

@graph = Koala::Facebook::API.new(oauth_access_token)@friends = @graph.get_connections("me", "friends")

sábado, 12 de maio de 12

Criando um Adapterclass FacebookAdapter attr_accessor :access_token, :adapter

def initialize(access_token, adapter = Koala::Facebook::API) @access_token = access_token @adapter = adapter.new(access_token) end

def friends adapter.get_connections("me", "friends", :fields => "name") endend

sábado, 12 de maio de 12

FINALIZANDO...

Ao codificar, vamospensar no DESIGN

sábado, 12 de maio de 12

OBRIGADO

sábado, 12 de maio de 12

top related