Posts in português

Ultimamente temos trabalhado em alguns projetos que necessitaram de vários CRUDs na administração como páginas mostrando listas de atributos. E com passar do tempo, estávamos ficando entediados de tanto copiar e colar código como este para cada atributo em nossas páginas:

<p>
  <strong class="label">Name</strong><br />
  <%= @person.name %>
</p>

Nós já tinhamos criado um helper para fazer o trabalho para nós, mas copiar este helper de um projeto para outro não é DRY. Então decidimos criar uma nova gem, chamada ShowFor.

ShowFor é uma DSL para auxiliá-lo a mostrar uma lista de atributos, usando I18n, perfeito para páginas de visualização em interfaces CRUDs. Ele permite que você substitua duplicação de código/html em suas views usando uma sintaxe mais atraente. Vejamos o que podemos fazer!

Atributos

Vamos imaginar que temos um model Person, que possui os atributos first_name, last_name, age, photo, e confirmed. As linhas abaixo criam uma lista de valores para um registro específico:

<% show_for @person do |p| %>
  <%= p.attribute :first_name %>
  <%= p.attribute :last_name %>
  <%= p.attribute :confirmed? %>
  <%= p.attribute :created_at, :format => :short %>
  <%= p.attribute :age, :if_blank => "No age" %>
 
  <% p.attribute :photo do %>
    <%= image_tag(@person.photo_url) %>
  <% end %>
<% end %>

E este é o código HTML que você tem como resultado:

<div class="show_for person" id="person_1">
  <p class="wrapper person_first_name"><strong class="label">First name</strong><br />Carlos</p>
  <p class="wrapper person_last_name"><strong class="label">Last name</strong><br />Antonio</p>
  <p class="wrapper person_confirmed"><strong class="label">Confirmed?</strong><br />Yes</p>
  <p class="wrapper person_created_at"><strong class="label">Created at</strong><br />08 Mar 11:30</p>
  <p class="wrapper person_age"><strong class="label">Age</strong><br />24</p>
  <p class="wrapper person_photo"><strong class="label">Photo</strong><br />
    <img alt="Rails" src="/images/rails.png?1268047643" />
  </p>
</div>

Como se pode ver, você terá uma marcação HTML padrão, com classes e ids para ajudá-lo no design com CSS. E caso tenha notado, estamos usando opções extras em alguns atributos, vamos dar uma olhada em algumas delas:

  • :format permite que você defina um formato a ser usando com I18n, somente para atributos date/time, como você usaria com o helper l.
  • :if_blank define o que será mostrado caso o atributo esteja em branco. Pode ter um valor padrão via I18n.
  • do...end: usando blocos você mesmo pode manusear o conteúdo para o atributo específico, como fizemos no exemplo para o atributo photo.

Atributos booleanos, como nosso :confirmed, também possuem um valor padrão para true e false, e podem ser configurados através de I18n. Se você deseja mostrar “Sim” e “Não” no lugar de “Yes” e “No” respectivamente, só precisa mudar seu arquivo I18n. Você também pode passar a opção :escape para não escapar o conteúdo (true por padrão).

Associações

ShowFor também funciona com associações. Por exemplo, podemos adicionar que nosso Person agora pertence a um model City com um atributo nome, e que também possui e pertence a muitas Tags. Para gerenciar o primeiro, podemos fazer:

<%= p.association :city %>

ShowFor irá adivinhar o atributo correto para mostrar procurando todas as possibilidades configuradas em ShowFor.association_methods e neste caso escolhendo :name. Mas é claro, você pode modificar isso se precisar:

<%= p.association :city, :using => :full_name %>
<%= p.attribute :full_name, :in => :city %>

Ambas as possibilidades acima terão a mesma saída, apenas escolha a que você mais gostar.

Manusear coleções é tão fácil quanto associações belongs_to. Você simplesmente passa a associação para ShowFor e ele irá saber se é uma coleção ou não, gerando uma lista de elementos usando tags ul e li.

<%= p.association :tags %>

Entretando, se você quiser renderizar a coleção inline, pode usar as opções :to_sentence e :join:

<%= p.association :tags, :to_sentence => true %>
<%= p.association :tags, :join => ',' %>

Também é possível passar um bloco para a coleção. O ShowFor criará a tag wrapper (ul por padrão nesse caso) e retornará cada elemento da coleção para você gerenciá-lo:

<% a.association :tags do |tag| %>
  <li><%= link_to tag.name, tag %></li>
<% end %>

Labels

Você deve ter percebido que o ShowFor possui um label padrão usando a tag strong. Ele também expõe a você o método label como um helper, para que possa usá-lo quando desejar:

  <%= p.label :first_name %>
  <%= p.label :age, :id => 'person_age' %>
 
  <strong class="label">First name</strong>
  <strong class="label" id="person_age">Age</strong>

Instalação

O ShowFor, em sua versão 0.2.0, já é compatível com o Rails 3. Você pode seguir as instruções no README para instalá-lo.

Se você está usando o Rails 2.3.x, pode dar uma olhada no branch 0.1, e seguir as instruções no README deste branch para utilizá-lo.

E após a instalação, não se esqueça de executar o generator e dar uma olhada no initializer gerado, que permite que você configure várias partes do ShowFor.

script/generate show_for_install

Fechando

ShowFor ajuda você a mostrar os atributos de seus objetos facilmente com uma marcação html padrão, e pode ser totalmente configurado para atender sua necessidade. Ele tem nos ajudado em todos os projetos, e esperamos que ele possa ajudá-lo também. Se você tiver alguma dúvida, por favor dê uma olhada no README, existem muitos exemplos e documentação lá.

E você? Possui algum helper que usa todos os dias e que poderia ser transformado em um plugin/gem? Não hesite em fazer isto, ficaremos contentes em ver seu trabalho!

Divirta-se!

Hoje estamos comemorando o aniversário do Devise. Mas espere um pouco, se você está seguindo o Devise desde o início pode estar se perguntando: “O Devise já completou um ano de vida?”. Não. Hoje estamos completando exatamente 4 meses desde que o Devise foi lançado no Rails Summit Latin America 2009. E estamos muito orgulhosos e felizes em dizer que alcançamos a versão 1.0! Yeah! Vamos comemorar e falar um pouquinho sobre a história do projeto.

O início

Decidimos criar o Devise com base em alguns requisitos de um projeto que tivemos no ano passado. A grande maioria de nossos projetos normalmente precisam de uma interface de administração para configurar a aplicação e alguma informação com CRUD. E neste projeto em específico, precisávamos de dois papéis diferentes na mesma aplicação: o administrador com todos os poderes para gerenciar a aplicação, e os usuários finais que deveriam estar devidamente logados para executarem algumas coisas na aplicação. Normalmente essa situação requer um modelo, com alguma coluna de “tipo” ou flag para determinar se o usuário é admin ou não, certo? Ok, mas não gostávamos muito deste método. Então começamos a analisar as possibilidades:

  • Authlogic: um código ótimo e cheio de funcionalidade, mas um pouco estranho gerenciando a sessão através de um modelo. Além disso, ele gerenciava apenas a parte do modelo.
  • Clearance: completo, funciona como Engine do Rails, módulos adicionais, tudo que precisávamos. Entretanto, ele nos obriga a usar o modelo User, sem possibilidade de customizar isto.

Certo, poderíamos escolher um deles e com um pouco de trabalho extra alcançaríamos nossos requisitos. Mas nós precisaríamos fazer isto toda vez que uma situação dessas acontecesse? Nós respondemos não. Não era DRY o suficiente. E nós gostamos de ser DRY. Então nasceu o Devise.

O principal objetivo da primeira versão do Devise era proporcionar o processo de login completo, incluindo recuperação de senha e confirmação de conta. E tudo deveria funcionar com papéis diferentes, o que significa que você poderia facilmente adicionar em sua aplicação um papel de Admin, User, Account, ou qualquer outro que precisasse, sem muito trabalho. Também tínhamos um prazo: o Rails Summit. Levou quase 1 mês de trabalho antes do Rails Summit. Ainda me lembro os dias que antecederam o evento, nós trabalhando quase como loucos para deixar o Devise redondo, e também o README que foi escrito durante o evento. Então, estávamos prontos e apresentando o Devise para o mundo.

Como ele funciona

O Devise nasceu com o intuito de gerenciar papéis diferentes sem esforço, automaticamente, e isso é conseguido através das Engines do Rails. Além disso, o Devise é construído sobre o Warden, um ótimo framework de autenticação para o Rack. Isso nos permitiu ser bastante flexíveis e adicionar estratégias diferentes, hooks, a módulos facilmente. Em resumo, o Devise:

  • É baseado no Rack;
  • É uma solução MVC completa com base em Rails Engines;
  • Permite que você tenha múltiplos papéis (modelos/escopos) logados ao mesmo tempo;
  • É totalmente baseado no conceito de modularidade: use somente o que você realmente precisa.

A estrada até agora

Devise foi lançado com os módulos básicos necessários para aquela aplicação específica:

  • Authenticatable: responsável por logar usuários atráves de formulários, gerenciando validação de senha e autenticação.
  • Confirmable: controla a confirmação de conta de usuários.
  • Recoverable: gerencia a recuperação de senhas.
  • Validatable: validação básica de email e senha.

Certo, tínhamos tudo que precisávamos até então. O restante estava em uma wishlist, a qual chamamos de TODO. E decidimos desde o princípio não adicionar funcionalidades ao Devise até que nós ou outra pessoa realmente precisasse. Mas as pessoas pediram, as pessoas precisavam de novas funcionalidades. E elas sempre estiveram lá para ajudar, para criar um fork e corrigir um bug, para comentar. Então logo começamos a adicionar novas funcionalidades, a primeira era:

  • Rememberable: gerencia o login automático de usuários a partir de cookies.

Depois as pessoas pediram por maneiras mais fáceis de criar as migratios, então introduzimos um novo módulo com o Devise 0.2:

  • Migratable: cria hooks nas migrations do ActiveRecord adicionando alguns métodos para criar os campos para o Devise. Assim você pode fazer coisas como t.authenticatable, t.confirmable e assim por diante.

Para ajudar as pessoas a iniciarem mais rapidamente, criamos então alguns geradores. Atualmente são eles:

  • script/generate devise_install: cria um arquivo de inicialização para habilitar algumas configurações e também copia o arquivo padrão de locale.
  • script/generate devise MyModel: cria um modelo já configurado para o Devise, adiciona rotas e uma migration.
  • script/generate devise_views: copia todas as views do Devise para seu diretório app/views, permitindo que você altere como achar necessário.

As versões 0.3 e 0.4 do Devise vieram logo em seguida, com vários bugs corrigidos nos geradores, I18n, inicialização, alguns métodos deprecados e uma porção de código refatorado.

As contribuições da comunidade estavam aparecendo cada vez mais. A primeira grande contribuição veio com a adição dos encryptors. Atualmente o Devise suporta a criptografia de senhas com SHA1, SHA512 e Bcrypt. Ele também possui suporte às mesmas rotinas de criptografia do Authlogic, Clearance e Restful Authentication, para auxiliá-lo a migrar dessas soluções.

Neste ponto pensamos: certo, já deve ser o bastante. Não era. As pessoas precisavam de ORMs diferentes do ActiveRecord. Então adicionamos suporte ao MongoMapper e estávamos alcançando o Devise 0.5.

Estávamos recebendo muito feedback sobre problemas com testes funcionais, então construímos o Devise::TestHelper, que contém métodos para auxiliar as pessoas com o processo de sign in/out nestes testes.

Conforme as aplicações crescem, mais papéis podem ser necessários. Então adicionamos a possibilidade de criar views específicas para cada papel/escopo de sua aplicação. Assim seu usuário poderia ter uma view para logar diferente do administrador, por exemplo. Chegando na versão 0.6, várias melhorias foram feitas na geração de rotas e o suporte ao DataMapper foi adicionado.

Estávamos cheio de idéias legais para adicionar novas funcionalidades, e nosso TODO estava maior do que gostamos. Então surgimos com:

  • Timeoutable: faz uma checagem em cada request para destruir a sessão do usuário após um certo período de inatividade, pedindo por credenciais novamente.
  • Trackable: registra o número de logins do usuário, última data/hora e ip usados para acessar.

Também o processo de carregamento e o suporte a diferentes ORMs receberam uma boa atenção com o lançamento do Devise 0.7.

Para a versão 0.8 do Devise melhoramos os testes para o MongoMapper e fizemos uma grande revisão no código. Algum esforço também foi feito para ter o Devise rodando com a última versão do Warden e as novas features, tais como os serializers. Outro módulo base foi extraído do Confirmable:

  • Activatable: permite configurar métodos adicionais para ativação de um modelo.

Com muito feedback vindo da comunidade, fizemos merge de uma nova funcionalidade bacana:

  • Lockable: bloqueia contas com base no número de tentativas de login inválidas.

Seguindo o mesmo padrão do Rails neste commit alteramos as mensagens flash para :notice e :alert, e lançamos o Devise 0.9. Passo a passo a versão 1.0 estava chegando.

O que há de novo

O Devise 1.0 traz uma grande variedade de funcionalidades legais. A comunidade parece estar realmente apreciando o Devise, e recebemos outra grande contribuição:

  • Token Authenticatable: valida a autenticidade de um usuário atráves do login com um token de autenticação (também conhecido como “token de acesso único”).

Além disso, criamos as duas funcionalidades mais pedidas para o Devise:

  • Registerable: controla o registro de usuários (sign up), e também edição/atualização das informações do usuário e cancelamento de conta.
  • HTTP Authenticatable: autenticação http basic.

Também adicionamos a possibilidade de usar o Migratable ao editar uma tabela, usando change_table, dentre outras correções.

O que vem agora

Estamos preparando um novo release do Devise totalmente compatível com o Rails 3. Isso significa que a partir de agora o Devise está fechado para desenvolvimento de novas funcionalidades no Rails 2.x. Vamos manter um branch da versão 1.0 no github para correção de bugs mantendo tudo funcionando.

Para terminar

Gostaríamos de dizer muito obrigado a todos que nos ajudaram a chegar a versão 1.0 e a quem está utilizando o Devise, testando, criando issues e nos dando todo este feedback.

Também, para aqueles que estavam no Rails Summit do ano passado, nós propusemos algo: alcançar o maior número de seguidores no github tão rápido quanto possível! Quando apresentamos o Devise, haviam 7 seguidores, e se estou correto nós eramos 4 deles. No momento da redação deste post nós temos 762 seguidores. Yeah! Acho que posso assumir o risco e dizer que nós conseguimos. Obrigado!

Vamos comemorar o Devise 1.0, e aguardar ansiosos para ver o Devise com o Rails 3. Aproveite!

Feliz aniversário Devise!

Então você já fez a feliz escolha de tratar seu processamento em background com Delayed Job, ótimo! Mas como ter certeza que esse processamento vai continuar acontecendo enquanto você estiver dormindo? E se o o processo do Delayed Job cair, você vai acordar de madrugada e levantá-lo na mão? Eu não faria isso, gosto do meu sono. Qual a solução então?

Não é nenhuma novidade para nós, rubyistas e railers, que existem soluções como o God para fazerem o trabalho de monitoramento de processos. No entanto, existem outras soluções, como o Bluepill. O Bluepill é uma ferramenta de monitoramento de processos assim como o God, mas diferente dele, não tem memory leak, segundo seus autores.

Bem, como não quero acordar de madrugada para levantar meu processo do Delayed Job na mão, e também não quero ficar restartando um processo do God por causa de memory leak, resolvi usar o Bluepill. Mas como uso o Bluepill para monitorar o Delayed Job?

Para configurar o Bluepill para monitorar o Delayed Job, e usar o Capistrano para automatizar algumas tarefas, temos basicamente 4 passos:

  1. Instalar e configurar o Delayed job
  2. Instalar e configurar o Bluepill
  3. Escrever a receita de capistrano para o Bluepill
  4. Setar algumas coisas do arquivo /etc/sudoers

Vamos dar uma olhada em detalhes em cada passo.

Instalação e configuração do Delayed Job

Instalar e configurar o Delayed Job é super simples, basta ler o README do projeto, que está bem claro. Recomendo também assistir ao RailsCast sobre o Delayed Job. Foi de lá que tirei a informação de usar o fork do Delayed Job da Collective Idea ao invés da versão do repositório original.

Instalação e configuração do Bluepill

Instalar o Bluepill também não tem muito segredo, basta você ler o README do projeto e seguir os passos que estão descritos lá.

Na parte da configuração, você pode ver as opções também no README do projeto. No meu caso, esse arquivo está em RAILS_ROOT/config/production.pill.

Bluepill.application("my_app") do |app|
  app.process("delayed_job") do |process|
    process.working_dir = "/home/deploy/my_app/current"
 
    process.start_grace_time    = 10.seconds
    process.stop_grace_time     = 10.seconds
    process.restart_grace_time  = 10.seconds
 
    process.start_command = "ruby script/delayed_job -e production start"
    process.stop_command  = "ruby script/delayed_job -e production stop"
 
    process.pid_file = "/home/deploy/my_app/shared/pids/delayed_job.pid"
    process.uid = "deploy"
    process.gid = "deploy"
  end
end

No entanto, eu tive um pequeno problema com a interação do Bluepill e o Delayed Job. Ao passar a flag -e production para o Delayed Job, ele não a estava interpretando direito. Você pode ver mais detalhes sobre isso numa issue que abri no repo do Delayed Job.

A primeira solução que pensei, foi usar RAILS_ENV=production ruby script/delayed_job start, no entanto por algum motivo que ainda desconheço, isso não funcionou.

A solução que cheguei então para resolver esse problema, foi modificar o arquivo que está em RAILS_ROOT/script/delayed_job para o seguinte:

1
2
3
4
5
6
7
8
9
#!/usr/bin/env ruby
 
# TODO improve the line of code below
# The line below is just a hack while we wait the delayed job guys answer the following issue
# http://github.com/collectiveidea/delayed_job/issues#issue/38
ENV['RAILS_ENV'] ||= "production"
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'config', 'environment'))
require 'delayed/command'
Delayed::Command.new(ARGV).daemonize

Como a flag -e production não estava sendo interpretada direito no Delayed Job, estou setando na mão o RAILS_ENV para production (linha 6), portanto estou supondo que você só está usando o Bluepill para monitorar processos do Delayed Job em environment igual a production.

Receita do Capistrano para o Bluepill

Para automatizar as tarefas de ligar e desligar o Bluepill, escrevi a seguinte receita de capistrano:

# deploy credentials
set :user, "deploy"
set :deploy_to, "/home/deploy/#{application}"
set :use_sudo, false
set :rails_env, "production"
 
# Bluepill related tasks
after "deploy:update", "bluepill:quit", "bluepill:start"
namespace :bluepill do
  desc "Stop processes that bluepill is monitoring and quit bluepill"
  task :quit, :roles => [:app] do
    sudo "bluepill stop"
    sudo "bluepill quit"
  end
 
  desc "Load bluepill configuration and start it"
  task :start, :roles =>[:app] do
    sudo "bluepill load /home/deploy/my_app/current/config/production.pill"
  end
 
  desc "Prints bluepills monitored processes statuses"
  task :status, :roles => [:app] do
    sudo "bluepill status"
  end
end

Note que ao invés de usar o método run do capistrano, estou usando o método sudo. Isso porque o comando bluepill deve ser rodado como root. Isso nos leva para o próximo tópico.

/etc/sudoers

Já que eu preciso rodar o comando bluepill como root, vou ter que mudar o meu set :user, "deploy" para set :user, "root"? Acho melhor não, não gostamos de dar acesso root para qualquer coisa, mesmo para deployment. Então, como fazer? Simples, basta editar seu arquivo de sudoers.

Para isso, você precisa usar o comando visudo para abrir e editar o arquivo /etc/sudoers. Uma vez com o arquivo aberto, adicione a seguinte linha no final do arquivo:

deploy ALL=(ALL) NOPASSWD: /usr/local/bin/bluepill

Pronto, agora o usuário deploy já pode fazer sudo bluepill sem precisar de senha. Problema resolvido sem colocar a segurança da sua máquina em risco. ;)

Depois de ter feito esses 4 passos, você está pronto para dormir a noite sem se preocupar com seu processo do Delayed Job. E quando quando quiser saber como está o status dos seus processos monitorados, basta usar a seguinte task do capistrano na sua máquina local:

cap bluepill:status

E você? Quais soluções você usa para dormir em paz?

Update: Se você está tendo problemas em restartar o Bluepill com o capistrano, dê uma olhada aqui.

2009 se foi. Foram 10 meses muito agitados para nós. Aprendizado intenso, momentos de cansaço físico, desafios constantes e dúvidas sobre o futuro são fatores que estão presentes no nosso dia-a-dia.

Antes de iniciar as operações da Plataforma Tecnologia (fev/09), nos questionávamos duas perguntas que davam frio na barriga:

Como fazer uma empresa de serviços dar certo?!
Como sair da inércia e conquistar os primeiros clientes?!

Não sabíamos as respostas. Mas estávamos lá.
Cada um com suas habilidades e todos com um sentimento que se equilibrava entre arrogância e inocência. Sem motivos muito claros, nós simplesmente acreditávamos que poderia dar certo.  Então, por que não tentar?

Aqui estamos: tentando.

É difícil dizer se a Plataforma Tecnologia será bem sucedida ou não. Só o futuro dirá.

O que podemos dizer é que avançamos muito mais do que imaginávamos e acreditamos estar na direção certa.  Sabemos onde queremos chegar, mas há inúmeros caminhos para escolher. Uns melhores, outros piores.

Fato é que durante 2009 descobrimos algumas coisas que consideramos valiosas e queremos compartilhar nossa opinião.  Seguem abaixo.

  • Contrate pessoas cujo trabalho você confia (e vice-versa): se você precisa micro-gerenciar sua equipe, então algo está errado. Micro-gerenciar times de desenvolvimento de software é uma tentativa (ruim) de assegurar a qualidade durante o processo produtivo. É preciso entender que o processo em si não é tão importante. O importante é o resultado final. Dê autonomia a sua equipe. Parta do pressuposto que sua equipe é capaz de atingir os objetivos até que seja provado o contrário (e se o “contrário” ocorrer, há diversas ações que podem ser tomadas, mas isso rende assunto para um outro post inteiro).
  • A maioria dos clientes descrevem soluções ao invés de descrever as reais necessidades: é natural que isso ocorra. E ao invés de culpá-los por não saberem descrever corretamente as necessidades, ajude-os a esclarecer qual o problema a ser resolvido. Em seguida, construa com ele uma solução (software).
    Não se esqueça que é o seu cliente que tem o conhecimento sobre o segmento/negócio e uma boa solução será resultado de um trabalho conjunto. Se um cliente não se dispuser a trabalhar em conjunto para desenhar uma solução, então caia fora. Este projeto terá grandes chances de ter problemas.
  • 6 meses é muito tempo para empresas recém-nascidas e pequenas: É importante saber onde se quer chegar, mas nesta fase da empresa, não faz muito sentido realizar planejamentos com horizontes longos. Muita coisa muda e muito rápido.
    Descobrimos que vale a pena fazer planejamentos com maior freqüência e com horizontes mais curtos. É como se a cada 6 meses a empresa estivesse realizando um “release”. Faça “retrospectivas”, “release plannings”, “sprint plannings” relativos à empresa e priorize a execução do que trará mais valor durante os próximos 6 meses. A grande vantagem de uma empresa de pequeno porte é sua capacidade de responder à mudanças (agilidade). Aproveite-a!
  • Nunca haverá momento ideal para implementar algo: já nos pegamos dizendo “assim que der uma sossegada, a gente começa a re-estruturar bla-bla-bla”. A verdade é que este momento de sossego dificilmente chegará, ainda mais se a empresa estiver em crescimento. Se há necessidade em implementar ou mudar algo na empresa, faça-o o quanto antes (ou de acordo com a prioridade). Esperar só vai piorar os sintomas que este problema estiver causando. Quanto mais você esperar, pior será.
  • Saiba claramente qual o seu DNA: isso pode soar um pouco filosófico, e de fato é. Mas é algo que se mostrou muito importante para nós. Todo o time deve saber e compartilhar dos valores que moldam as decisões de negócio e refletem na maneira de operar o dia-a-dia da empresa. Pode ocorrer momentos em que fechar um novo contrato significará deixar o DNA de lado e isso será um pouco doloroso.
    Mas da nossa experiência, posso afirmar que valeu a pena não se desviar do DNA. Quando olhamos para trás, fica muito claro que tomamos boas decisões. Warren Buffet já dizia… “In the business world, the rear view mirror is always clearer than the windshield“.
    É a mais pura verdade!

Espero que estes tópicos possam ajudar startups e outras empresas iniciantes.

Gostaria de pedir que ajudem a enriquecer o post e comentem. Compartilhem suas experiências!

UPDATE: Graças ao @agaelebe o vídeo da apresentação está disponível aqui.

José Valim no #devinsampa

foto por: Silvio Tanaka. Veja outras do Dev in Sampa no flickr.

O Dev in Sampa ocorreu neste final de semana e creio que excedeu as expectativas de todos presentes! As palestras foram muito interessantes, algumas de opiniões fortes, como a do @fnando dizendo que você deve testar javascript e a do @guilhermecaelum e @adrianoalmeida7 que convenceram todos a estudar mais sobre o http antes de utilizá-lo, e outras sobre assuntos que estão bastante em discussão, como a do @lfcipriani sobre XMPP e a do @rferraz sobre como criar sua própria linguagem de programação. Um evento como o Dev in Sampa incentiva toda a comunidade e reforça a qualidade da mesma. Parabéns aos organizadores @tinogomes, @nuxlli e @lfcipriani!

Sem mais delongas, seguem os slides da minha apresentação. Assim que os vídeos forem disponibilizados postarei um link aqui!

O Dev in Sampa acontecerá no dia 28 de novembro (sábado) e, obviamente, será em São Paulo.

O José Valim participará falando sobre “Tópicos de machine learning: classificação de textos”. Será uma palestra baseada no seu trabalho de mestrado na Politécnica de Turim, na Itália.

Além disso, teremos palestras sobre jogos em Python, Arduino, testes em Javascript, Treetop, XMPP… o evento promete!

Confira a programação do evento!