Nos Trilhos com RAILS
Sylvestre Mergulhão
Necessidades
Desenvolver para a web
Desenvolver para a web de forma organizada
Desenvolver para a web de forma fácil de manter
Desenvolver para a web de forma fácil
Desenvolver para a web de forma rápida
Desenvolver para a web de forma (mais formas???)
Motivação n° 1/3
Java
Muito trabalho para pouco resultado
Java+Struts
Muita(mesmo!) configuração e muito(mesmo!) trabalho
para pouco resultado
PHP
Muita liberdade resulta em pouca organização
Motivação n° 2/3
Comparativos encontrados na Internet de um tal de
framework Ruby on Rails (RoR ou apenas Rails) com o
Struts.
Alguns chegavam a dizer num total de 10:1 em relação a
quantidade de linhas de código entre um e outro, mas
sem muitos detalhes.
Por que não pagar pra ver?
Motivação n° 3/3
Na verdade não paguei, recebi... pois estava no
horário de expediente.
Download e instalação de linguagem, bibliotecas,
conector para o banco de dados Postgresql e o
framework RoR: 1h.
Desenvolvimento passo-a-passo de uma aplicação CRUD
seguindo um tutorial: 1h.
Resultado
Duas aplicações...
Uma em Java+Struts+Hibernate
Outra em Ruby on Rails
O mesmo banco de dados...
O mesmo cérebro...
Introdução ao Ruby
“Uma linguagem que não afeta seu
jeito de pensar sobre programação
não vale a pena aprender”
Alan Jay Perlis
Cientista da computação
Conceitos utilizados pelo Ruby
Ruby? Oh, quanta preciosidade...
DRY. Poxa, mas por que tão seco?
KISS. Tomara que não seja o Last.
POLS: A lógica da menor surpresa.
Algumas características
Orientação a objetos sempre!
Tipificação forte, mas dinâmica
Atributo de classe? sempre privado...
acesso só por métodos...
Orientação a objetos sempre!
Tudo(mesmo!) é um objeto.
puts "alguma coisa".upcase # imprimirá "ALGUMA COISA"
Tipificação forte, mas dinâmica
num = 81
6.times do
puts "#{num.class}: #{num}"
num *= num
end
Fixnum:
Fixnum:
Fixnum:
Bignum:
Bignum:
Bignum:
81
6561
43046721
1853020188851841
3433683820292512484657849089281
11790184577738583171520872861412518665678211592275841109096961
Outros tipos
Fixnum
Bignum
Float
Range – representa intervalo de valores como
1..10 ou b..e;
Expressão regular – representa uma expressão regular
/a/ ou /^\s*[a-z]/
Um Array...
meu_array = [3,6,7,10]
Um Hash...
meu_hash = {:nome => 'Sylva', :telefone => '(21)8106-9960'}
Getter e setter? Simples...
class Carro
attr_accessor :modelo, :fabricante
end
Herança e métodos/operadores
class Numero < Fixnum
def +(numero)
71
end
end
Blocos de código
3.times { puts "Ruby rulez!" } # Irá imprimir 3 vezes
# "Ruby rulez!"
3.times do # Irá imprimir 6 vezes "Ruby rulez!"
puts "Ruby rulez!"
puts "Ruby rulez!"
end
Muitas outras funcionalidades
Módulos, Mixins, tratamento de exceção, etc...
O framework Rails
O framework Rails
Framework MVC
3 módulos principais:
. Active Record – ORM
. Action Controller
. Action View
Utiliza os mesmos conceitos do Ruby e mais um,
chamado Convention over Configuration.
Configuração só é necessária quando não existe
padrão.
Estrutura de diretórios 1/2
minha_aplicação/
/app
- arquivos dos modelos, visões e controles
/components - componentes reutilizáveis
/config
- arquivos de configuração, como de banco
de dados, por exemplo
/db
/doc
/lib
/log
/public
- arquivos do schema do banco de dados
- Documentação gerada automaticamente
- código compartilhado
- arquivos de log gerados pela aplicação
- o diretório que é acessível pela web. Da
visão do navegador parece que toda a
aplicação roda daqui
/scripts
/test
/vendor
- conjunto de scripts utilitários
- local para os testes de unidade,
funcionais, mock objects e fixtures
- códigos de terceiros, como plugins
Estrutura de diretórios 2/2
app/
/controllers - onde são colocados os controladores
/helpers
- onde são colocados os helpers
/views
- onde são colocados arquivos de visão
/models
- onde são colocados os modelos
e templates
Active Record, o salvador!
A classe que representa o modelo
class Client < ActiveRecord::Base
validates_uniqueness_of :login, :name
validates_presence_of :login, :name, :password
validates_confirmation_of :password
def self.login(login, password)
find(:first, :conditions => ["login = ? and password
= ?",login,password])
end
def try_to_login
Client.login(self.login, self.password)
end
end
Active Record
Requisição ao Banco de Dados
Quero buscar o cliente com login “sylva”! oh quem
poderá me ajudar?
Client.find(:first, :conditions => ["login = ?","sylva"])
Client.find_by_login("sylva")
Active Record
Requisição ao Banco de Dados
De onde surgiram os métodos 'find' e 'find_by_login'??
Eles não estão definidos na classe Client!
Simple!
It's a kind of magic!
\o/
Active Record
Requisição ao Banco de Dados
Na verdade, nem tanto... é simplesmente herança...
class Client
...
...
...
end
< ActiveRecord::Base
Active Record
Requisição ao Banco de Dados
Então, nenhum código precisou ser escrito para buscar
um cliente no banco.
Bastou invocar o método que é herdado do ActiveRecord
and it's done!
Em Hibernate....
Após escrever o XML de mapeamento,
gerar a fábrica de requisições, resgatar a sessão e
outras coisas mais...
package org.gula.persistence.dao;
import java.util.ArrayList;
import java.util.Collection;
import org.gula.entity.Cliente;
import org.hibernate.*;
import org.hibernate.criterion.Expression;
import org.gula.persistence.dao.DAOException;
import org.gula.persistence.HibernateUtil;
public class ClienteDAO {
...
public Cliente retrieve(Cliente clientePk) throws DAOException
{
Cliente cliente;
Session session = null;
try
{
session = HibernateUtil.currentSession();
cliente = (Cliente) session.createCriteria(Cliente.class).add( Expression.eq( "login", clientePk.getLogin()))
.uniqueResult();
HibernateUtil.closeSession ();
}
catch (Exception e)
{
throw new DAOException(e);
}
return cliente;
}
}
Como pode-se
perceber,
a diferença é
grande....
Active Record
Mapeamento dos relacionamentos
Usando-se a convenção do Rails fica simples e,
SEM CONFIGURAÇÃO!
class Sale < ActiveRecord::Base
has_many :sale_items
(...)
end
class SaleItem < ActiveRecord::Base
belongs_to :product
belongs_to :sale
(...)
end
Beans? Pra que feijões?
Struts faz validação dos FORMULÁRIOS
ActionForm ou DynaActionForm
Diretamente na Action, via método validate() no
ActionForm ou via Validator Framework (mais xml! ¬¬)
Beans? Pra que feijões?
Validação do modelo, não do formulário...
Validação fica junta com o modelo.
class Product < ActiveRecord::Base
belongs_to :category
belongs_to :manufacturer
validates_uniqueness_of :nome
validates_presence_of :nome
validates_presence_of :category_id
validates_presence_of :manufacturer_id
validates_numericality_of :preco
validates_numericality_of :estoque
...
end
Beans? Pra que feijões?
Se as validações default não forem suficientes
basta definir o método validate() dentro do modelo
E mais!
Pode ser sobrecarregado também o método
validate_on_create() e validate_on_update()
Os nomes seguem o POLS ;)
class Product < ActiveRecord::Base
belongs_to :category
belongs_to :manufacturer
(...)
protected
def validate
errors.add(:preco, 'Preço negativo') unless preco.nil? || preco > 0.0
end
def validate_on_create
errors.add(:picture, l(:error_jpeg)) if self.imagem.empty? || validate_content
end
def validate_on_update
if self.imagem.empty?
@product = Product.find(self.id)
self.imagem = @product.imagem
return
end
errors.add(:picture, l(:error_jpeg)) if validate_content
end
(...)
end
Sessões em Rails... just KISS!
Atributo session sempre disponível dentro
dos controladores permite uso fácil da sessão...
Como num Hash.
def authorize
unless session[:client_id]
flash[:notice] = l(:do_login)
session[:jumpto] = request.parameters
redirect_to(:controller => "client", :action => "login")
end
end
O que foi desenvolvido?
Foram desenvolvidas duas aplicações muito
semelhantes na interface e que utilizam a mesma
base de dados.
As duas possuem as mesmas funcionalidades e operam
da mesma forma do ponto de vista do usuário.
Uma foi desenvolvida em Java+Struts+Hibernate. A
outra em Ruby on Rails.
Comparativo numérico
SLOCCount - http://www.dwheeler.com/sloccount/
CLOC - http://cloc.sourceforge.net/
Contadores de linhas de código. Ignoram linhas em
branco e comentários.
Número de linhas de código
4000
3750
3500
3250
3000
2750
2500
2250
2000
1750
1500
1250
1000
750
500
250
0
Linhas
Ruby 681
Java 3854
Java
Ruby
Relação de 1:5,66
Número de arquivos de código
45
42,5
40
37,5
35
32,5
30
27,5
25
22,5
20
17,5
15
12,5
10
7,5
5
2,5
0
Arquivos
Ruby
24
Java
44
Relação de 1:1,833
Java
Ruby
Número de linhas de templates
900
Linhas
RHTML 500
JSP
875
800
700
600
500
JSP
RHTML
400
300
200
100
0
Relação de 1:1,75
Número de arquivos de template
27,5
25
Arquivos
RHTML
25
JSP
26
22,5
20
17,5
15
12,5
10
7,5
5
2,5
0
JSP
RHTML
Quase a mesma
relação
Número de linhas em
arquivos de configuração
YAML
XML
Linhas
18
273
275
Vale a pena calcular
250
essa relação?
225
200
175
YAML
XML
Linhas
18
273
Apenas para manter
a apresentação em
150
125
XML
YAML
conformidade: 1:15.
100
75
50
25
0
PS: Nas 18 linhas
YAML estão
configurados 3
bancos: devel, test
e prod.
O trabalho buscou mais que
ser um simples comparativo
de linhas de código.
Na pequena aplicação
desenvolvida, o Rails mostrou
como a lógica de sua
implementação deixa as coisas
mais simplificadas para os
desenvolvedores.
Claro que usar apenas um
caso como verdade universal
não é correto.
Mas ele se mostrou preparado
para os desafios de grandes
sistemas web.
“Ruby on Rails: porque
programação não precisa ser
entediante.”
Fabio Akita
Programador Java
O futuro é livre. Open your minds.
Obrigado!
Contato:
Sylvestre Mergulhão
[email protected]
O futuro é livre. Open your minds.
Download

Nos Trilhos com RAILS