Posts de ‘Felipe Santiago’

[Felipe Santiago] Comportamento humano e o ambiente corporativo

Thursday, March 18th, 2010

Venho percebendo por todas as empresas por onde passei que algumas pessoas apresentam um comportamento não muito “ideal” no que tange a divisão de tarefas mais desafiadoras e as mais triviais. Ainda não pude concluir o motivo desse tipo de comportamento, mas espero encontrar mais respostas aqui neste espaço.

Todo tipo de trabalho é dividido entre atividades triviais e desafiadoras. Nós tendemos a rejeitar as triviais por acharmos que podemos contribuir mais para a empresa em que trabalhamos. Entretanto, quando se trabalha em equipe, é preciso entender que as outras pessoas que compartilhamos a maior parte do dia também tem o mesmo desejo: contribuir mais para a empresa. Portanto eu penso que, uma das características da maturidade profissional é ter discernimento sobre essa divisão de atividades: um dia você encara um desafio maior, outro dia você permite que seu colega encare.

Fazendo isso, é possível que os próprios colegas de trabalho consigam manter sua equipe motivada, sem a intervenção de um gerente. Falando por mim, acredito que todas as pessoas da minha equipe (que desenvolve software web) tem muito tesão no que faz e ficaria feliz em poder sempre enfrentar desafios maiores, e não ficar no marasmo da mesmice. Todos aqui brigam por isso e é muito satisfatório ver esse comportamento.

Por outro lado, já ouvi de ex-gerentes que deveríamos encarar, mesmo as tarefas triviais, como desafiadoras. Esse argumento, no fundo, tem um sabor psicológico da relação empresa x empregador: se recebe dinheiro por isso, deve fazer e pronto. Entretanto, penso que a grande maioria das pessoas que trabalham comigo não estão aqui apenas por dinheiro: elas querem se sentir desafiadas, motivadas e valorizadas.

Agora, voltando a questão do comportamento humano citado anteriormente, podemos concluir que se trata de falta de maturidade profissional (falta de percepção) ou egoísmo mesmo (uma falha de caráter) ?

[Felipe Santiago] Novo Primeira Chance

Saturday, March 6th, 2010

Como eu disse no primeiro post do ano, estou planejando ações para os próximos 5 anos. E uma delas é a reformulação um dos sites que criei, o Primeira Chance. A primeira medida foi criar o blog oficial do site, que será responsável por ser o canal principal de comunicação da nossa equipe com os usuários.

O Primeira Chance foi uma grata surpresa em minha vida, apesar de ter dados reais que poderia se tornar um sucesso. O site cresceu em um espaço não preenchido pelas empresas de recursos humanos. Espaço esse que consiste em dar uma atenção especial para as pessoas que desejam entrar no mercado do trabalho e pôr em prática o que aprenderam na sala de aula.

Foi em Setembro de 2008 que tive a ideia de lançar o projeto, após perceber a dificuldade de encontrar informações sobre vagas de estágio. Hoje, com quase 2 anos, temos uma média diária de 3.500 acessos únicos. É claro que eu não consegui isso sozinho: tive o apoio e contribuição irrestritos da minha namorada, a Rê Souza. Sem ela, acredito que o projeto estaria em coma ou até mesmo teria morrido.

Apesar de termos atingido um ótimo patamar, queremos mais: oferecer um melhor serviço, tanto para os candidatos quanto para os recrutadores. O Novo Primeira Chance vai ser um marco, e espero anunciá-lo em breve. Para se increver e poder testar a versão beta, preencha o cadastro no blog oficial. Acompanhe de perto do blog oficial para saber das novidades.

[Felipe Santiago] Estréia 2010

Monday, February 22nd, 2010

Passados praticamente 2 meses, o ano finalmente está começando, uma vez que ultrapassamos o Carnaval, e estou dando início oficialmente aos meus objetivos para os próximos 5 anos. O primeiro deles é finalizar meu site pessoal, que está sendo feito de forma incremental. Estou disponibilizando aqui todos os artigos técnicos que um dia eu publiquei (no startapp.org, blog da fábrica entre outros).

Ainda possuo na fila 2 artigos por terminar, sobre Sitemap e RSS em Rails, mas é certo que cada vez menos compartilharei dos meus conhecimentos técnicos aqui, devido ao vasto material que é possível encontrar na internet: eu realmente não gosto de parecer redundante. Irei focar, daqui por diante, nas minhas observações pessoais sobre o mundo, cotidiano, e tentarei ajudar no dia-a-dia de vocês, seja no trabalho ou na vida. Sim, não é pretensão, mas acredito que posso compartilhar um pouco do que acredito e ajudar a fazer a diferença no nosso amado país.

Até o próximo post, sobre empreendedorismo.

[Felipe Santiago] Adicionando dados ao banco corretamente com Rails

Friday, November 27th, 2009

Essa dica é rápida porém muito eficaz. No Rails 2.3.4 foi adicionado uma funcionalidade para podermos popular nossa base de dados de forma segura e correta, pois antes tínhamos que criar migrations de dados de exemplo ou até mesmo os primeiros dados de configuração da aplicação.

Agora basta criar um arquivo chamado seeds.db dentro da pasta db da sua aplicação. Nele você pode chamar os objetos Rails normalmente como o código abaixo:

 
puts "Adicionando usuario admin"
u = User.new(
            :email => "admin@testecom",
            :login => "admin",
            :password => "12345",
            :password_confirmation => "12345",
            :admin => true
            )

Para rodar a massa de dados basta executar:

rake db:seed

Não está mais fácil e organizado ? Até a próxima.

[Felipe Santiago] Adicionando dados ao banco corretamente com Rails

Friday, November 27th, 2009

Essa dica é rápida porém muito eficaz. No Rails 2.3.4 foi adicionado uma funcionalidade para podermos popular nossa base de dados de forma segura e correta, pois antes tínhamos que criar migrations de dados de exemplo ou até mesmo os primeiros dados de configuração da aplicação.

Agora basta criar um arquivo chamado seeds.db dentro da pasta db da sua aplicação. Nele você pode chamar os objetos Rails normalmente como o código abaixo:

 
puts "Adicionando usuario admin"
u = User.new(
            :email => "admin@testecom",
            :login => "admin",
            :password => "12345",
            :password_confirmation => "12345",
            :admin => true
            )

Para rodar a massa de dados basta executar:

rake db:seed

Não está mais fácil e organizado ? Até a próxima.

[Felipe Santiago] SQLAlchemy e memcached

Friday, November 6th, 2009

Quando falamos de aplicações de alta perfomance, falamos basicamente em cache, cache e mais cache. E então, nos deparamos com a seguinte pergunta: como integrar uma ferramenta de mapeamento de objetos relacionais (ORM), que mantém associação e relacionamentos entre objetos em sessão, com uma solução de cache, como o memcached ? Complicou ? Então acalme-se, pois iremos explicar como fazer de uma forma limpa e elegante.

Para começar vamos falar um pouco do ORM SQLAlchemy, que estamos utilizando em um projeto. O SQLAlchemy é um framework python responsável por transformar suas tabelas em objetos relacionais, a fim de abstrair todo acesso ao banco, dando total flexibilidade ao desenvolvedor. Está atualmente na versão 0.5.6 e entre suas principais features estão, pool de conexões e gerencia de sessão. Nosso foco aqui não é se aprofundar no SQLAlchemy, mas sim em como integrá-lo com o memcached.

O grande gargalo das aplicações atualmente é, sem dúvida, o acesso ao banco, e para resolver esse problema nós utilizamos cache em memória, a fim de evitar acessar o banco toda vez que se quer ter acesso a alguma informação. O problema é que quando utilizamos um ORM, ele fica responsável pelo acesso ao banco e você perde o controle sobre as operações realizadas. O que nós queremos é ter o poder de um ORM, aliado ao poder do cache, e a solução passa por criar uma abstração no SQLAlchemy, que verifique se um determinado objeto está no cache, e ir ao banco somente se o ele não existir em cache.

Isso pode parecer simples, mas o SQLAlchemy na atual versão, mantém os objetos em sessão, para aumentar a performance, evitando ir ao banco sempre que um objeto é requisitado pela aplicação, e somente ele tem o controle desses objetos. Imagine que tenhamos uma associação simples entre jogador e clube, onde um jogador pertence a um único clube. Vejamos o exemplo abaixo:

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, scoped_session
from sqlalchemy import create_engine
 
Base = declarative_base()
class Jogador(Base):
 
    __tablename__ = 'jogador'
 
    id = Column('jogador_id', Integer, primary_key=True)
    nome = Column('nome_txt', String)
    clube_id = Column('clube_id', Integer, ForeignKey("clube.clube_id"))
    clube = relation(Clube, backref="jogadores")
 
# cria uma sessão com o banco
engine = create_engine('mysql://root:@localhost/teste', echo=True)
session = scoped_session(sessionmaker(bind=engine, autocommit=True, autoflush=True))
 
jogador = session.query(Jogador).get(id) #recupera o jogador de id=1
clube = jogador.clube #recupera o clube do jogador
print "o nome do jogador e %s" %clube.nome

Ao procurar por um jogador, o ORM verifica se ele está na sessão, se não estiver ele irá executar um SELECT no banco, o mesmo acontecendo com o clube. Entretanto, nós desejamos que antes dele fazer acesso ao banco verifique se o mesmo está em cache. Para isso precisamos sobreescrever o objeto query da sessão do SQLAlchemy, criando uma classe, CachedQuery, que extende sqlalchemy.orm.query.Query e implementa essa lógica.

import memcache
from sqlalchemy.orm.query import Query
 
cache = memcache.Client(['127.0.0.1:11211'], debug=0)
 
class CachedQuery(Query):
 
    def get(self, ident, **kw):
 
        mapper = self._mapper_zero()
        session = self.session
 
        # gera uma chave para o objeto
        key = mapper.identity_key_from_primary_key(ident)
 
        # pega o objeto da sessão, se existir
        cacheobj = session.identity_map.get(key)
 
        # gerando uma chave para o memcached module.Classe(id)
        cache_key = "%s.%s%s" % (key[0].__module__,key[0].__name__,key[1])
 
        if not cacheobj:
 
            # pega o objeto do memcached, se existir
            cacheobj = cache.get(cache_key)
 
            if cacheobj is not None:
                # recuperando do cache e setando na sessao
                cacheobj.__dict__["_sa_instance_state"] = attributes.instance_state(cacheobj)
                session.add(cacheobj)
            else:
                # nao existe no cache, pega do banco
                cacheobj = super(CachedQuery, self).get(ident)
                if cacheobj is None:
                    return None
                # setando objeto no cache
                cache.set(cache_key, cacheobj)
        else:
            # recuperando da sessao
            pass
 
        return cacheobj

Perceba que ao extender Query e sobreescrever o método get, estamos alterando apenas o seu comportamento, não interferindo no resto da classe. Poderíamos sobreescrever também os metodos save, update e delete, para salvar, atualizar e remover o objeto também do cache. Depois de criada a classe CachedQuery basta instanciar a sessão do SQLALchemy, utilizando essa classe. voltando ao nosso exemplo do jogador a create_session ficaria da seguinte forma

 
..
 
# cria uma sessão com o banco
engine = create_engine('mysql://root:@localhost/teste', echo=True)
session = scoped_session(sessionmaker(bind=engine, autocommit=True, autoflush=True, query_cls=CachedQuery))
 
...

A partir daqui todo acesso ao banco passará antes pelo memcached aumentando de forma exponencial a performance de sua aplicação.

[Felipe Santiago] Localização e Rails 2.3

Tuesday, September 29th, 2009

De vez em quando somos desafiados a desenvolver projetos que necessitam de traduções para outras línguas. Para resolver isso, usamos técnicas de localização.O Rails facilita muito a nossa vida ao guardar mensagens de erro e todo o texto customizado que você desejar traduzir em apenas um lugar.

Abaixo segue um exemplo de um trecho do arquivo de tradução com mensagens de erro do Active Record traduzidos para português:

:activerecord => {
      :errors => {
        :template => {
          :header => {
            :one => "Identificamos 1 erro nesta operação",
            :other => "Identificamos {{count}} erros nesta operação"
          },
          :body => "Por favor, confira os seguintes campos:"
        },
        :messages => {
          :inclusion => "não está incluso na lista",
          :exclusion => "não está disponível",
          :invalid => "não é válido",
          :confirmation => "é diferente da confirmação",
          :accepted  => "precisa ser aceito",
          :empty => "não pode ser vazio",
          :blank => "não pode ser vazio",
          :too_long => "é muito longo (deve ser menor que {{count}} caracteres)",
          :too_short => "é muito curto (deve ser maior que {{count}} caracteres)",
          :wrong_length => "não é do tamanho correto (precisa ter {{count}} caracteres)",
          :taken => "não está disponível",
          :not_a_number => "não é um número",
          :greater_than => "precisa ser maior do que {{count}}",
          :greater_than_or_equal_to => "precisa ser maior ou igual a {{count}}",
          :equal_to => "precisa ser igual a {{count}}",
          :less_than => "precisa ser menor do que {{count}}",
          :less_than_or_equal_to => "precisa ser menor ou igual a {{count}}",
          :odd => "precisa ser ímpar",
          :even => "precisa ser par",
        }
      },

Seguindo o tutorial, para ativar a localização em um aplicativo Rails, basta definir as seguintes configurações em seu arquivo enviroment.rb:

config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}')]
config.i18n.default_locale = 'pt-BR'

Dessa forma, define-se uma linguagem padrão para todo o site. Se quisermos alterar a linguagem durante a renderização das páginas, passando parâmetro na URL, pode-se definir os seguintes parâmetros no application controller.

before_filter :set_locale
 
def set_locale
    # update session if passed
    session[:locale] = params[:locale] if params[:locale]
 
    # set locale based on session or default 
    I18n.locale = session[:locale] || I18n.default_locale
 
    # load locale from settings
    @locale_files = []
    ['yml', 'rb'].each do |type|
      locale_file = "#{LOCALES_DIRECTORY}#{I18n.locale}.#{type}"
      if File.exists?(locale_file)
        @locale_files << locale_file
        I18n.load_path << locale_file
      end
    end
  end

Como viram, é bastante fácil “localizar” em Rails. Se você desejar também traduzir o conteúdo das páginas. Veja o codigo abaixo:

},
      :home => {
        :see_more_link => "Veja mais {{more_link}}",
        :see_all_link => "Saiba tudo sobre este {{all_link}}",
        :video_box_title => "Aperitivo",
        :events_box_title => "Últimos Eventos",
        :blog_box_title => "Blog",
        :followers_box_title => "Fãs",
        :scrapbook_box_title => "Scrapbook",
        :shopping_box_title => "Shopping"
      },

Criamos um dicionário de ítens a serem traduzidos. No template HTML, você deve fazer da seguinte forma:

<h1><%= I18n.t 'txt.home.video_box_title' %></h1>

Mais uma vez comprovamos a facilidade de traduzir com Rails. Para ter o arquivo de localização completo, entre em contato comigo que eu enviarei, pois ainda não disponibilizei no github. Se for urgente, você poderá encontrar em alguns perfis onde achei o modelo para me basear.

[Felipe Santiago] Localização e Rails 2.3

Tuesday, September 29th, 2009

De vez em quando somos desafiados a desenvolver projetos que necessitam de traduções para outras línguas. Para resolver isso, usamos técnicas de localização.O Rails facilita muito a nossa vida ao guardar mensagens de erro e todo o texto customizado que você desejar traduzir em apenas um lugar.

Abaixo segue um exemplo de um trecho do arquivo de tradução com mensagens de erro do Active Record traduzidos para português:

:activerecord => {
      :errors => {
        :template => {
          :header => {
            :one => "Identificamos 1 erro nesta operação",
            :other => "Identificamos {{count}} erros nesta operação"
          },
          :body => "Por favor, confira os seguintes campos:"
        },
        :messages => {
          :inclusion => "não está incluso na lista",
          :exclusion => "não está disponível",
          :invalid => "não é válido",
          :confirmation => "é diferente da confirmação",
          :accepted  => "precisa ser aceito",
          :empty => "não pode ser vazio",
          :blank => "não pode ser vazio",
          :too_long => "é muito longo (deve ser menor que {{count}} caracteres)",
          :too_short => "é muito curto (deve ser maior que {{count}} caracteres)",
          :wrong_length => "não é do tamanho correto (precisa ter {{count}} caracteres)",
          :taken => "não está disponível",
          :not_a_number => "não é um número",
          :greater_than => "precisa ser maior do que {{count}}",
          :greater_than_or_equal_to => "precisa ser maior ou igual a {{count}}",
          :equal_to => "precisa ser igual a {{count}}",
          :less_than => "precisa ser menor do que {{count}}",
          :less_than_or_equal_to => "precisa ser menor ou igual a {{count}}",
          :odd => "precisa ser ímpar",
          :even => "precisa ser par",
        }
      },

Seguindo o tutorial, para ativar a localização em um aplicativo Rails, basta definir as seguintes configurações em seu arquivo enviroment.rb:

config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}')]
config.i18n.default_locale = 'pt-BR'

Dessa forma, define-se uma linguagem padrão para todo o site. Se quisermos alterar a linguagem durante a renderização das páginas, passando parâmetro na URL, pode-se definir os seguintes parâmetros no application controller.

before_filter :set_locale
 
def set_locale
    # update session if passed
    session[:locale] = params[:locale] if params[:locale]
 
    # set locale based on session or default
    I18n.locale = session[:locale] || I18n.default_locale
 
    # load locale from settings
    @locale_files = []
    ['yml', 'rb'].each do |type|
      locale_file = "#{LOCALES_DIRECTORY}#{I18n.locale}.#{type}"
      if File.exists?(locale_file)
        @locale_files << locale_file
        I18n.load_path << locale_file
      end
    end
  end

Como viram, é bastante fácil “localizar” em Rails. Se você desejar também traduzir o conteúdo das páginas. Veja o codigo abaixo:

},
      :home => {
        :see_more_link => "Veja mais {{more_link}}",
        :see_all_link => "Saiba tudo sobre este {{all_link}}",
        :video_box_title => "Aperitivo",
        :events_box_title => "Últimos Eventos",
        :blog_box_title => "Blog",
        :followers_box_title => "Fãs",
        :scrapbook_box_title => "Scrapbook",
        :shopping_box_title => "Shopping"
      },

Criamos um dicionário de ítens a serem traduzidos. No template HTML, você deve fazer da seguinte forma:

<h1><%= I18n.t 'txt.home.video_box_title' %></h1>

Mais uma vez comprovamos a facilidade de traduzir com Rails. Para ter o arquivo de localização completo, entre em contato comigo que eu enviarei, pois ainda não disponibilizei no github. Se for urgente, você poderá encontrar em alguns perfis onde achei o modelo para me basear.

[Felipe Santiago] Dev in Rio 2009

Sunday, August 23rd, 2009

Dev in Rio 2009

Mais um evento muito legal promete agitar e marcar o cenário carioca de desenvolvimento de software. Será realizado dia 14 de setembro o Dev in Rio, um evento que terá vários ícones nacionais e internacionais representando diversas comunidades de tecnologias. Um dos organizadores é meu colega de trabalho Guilherme Chapiewski, famoso por diversas palestras que já fez em sua carreira, além de ser um grande desenvolvedor.

O evento que também é organizado pelo Henrique Bastos, contará com as presenças de Ryan Ozimeck, Guilherme Silveira, Nico Steppat, Fábio Akita, Jacob Kaplan-Moss, Jeff Patton e Vinícius Manhães Teles.

Confira toda a programação no site do evento e não deixe de participar.

[Felipe Santiago] Dev in Rio 2009

Sunday, August 23rd, 2009

Dev in Rio 2009

Mais um evento muito legal promete agitar e marcar o cenário carioca de desenvolvimento de software. Será realizado dia 14 de setembro o Dev in Rio, um evento que terá vários ícones nacionais e internacionais representando diversas comunidades de tecnologias. Um dos organizadores é meu colega de trabalho Guilherme Chapiewski, famoso por diversas palestras que já fez em sua carreira, além de ser um grande desenvolvedor.

O evento que também é organizado pelo Henrique Bastos, contará com as presenças de Ryan Ozimeck, Guilherme Silveira, Nico Steppat, Fábio Akita, Jacob Kaplan-Moss, Jeff Patton e Vinícius Manhães Teles.

Confira toda a programação no site do evento e não deixe de participar.