November 1, 2009
Java, Programação, Vida
No Comments
O novo site do PagSeguro não foi apenas uma melhoria no código antigo, foi muito mais que isso. O novo site do PagSeguro foi a reescrita completa de um enorme sistema que estava em produção.
A entrada em produção começou no dia 30/10/2009 no início da noite, onde o sistema antigo foi alterado para não permitir a utilização do saldo nem o login dos usuários. Após um certo tempo, a migração de dados do sistema antigo para o sistema novo foi iniciada. Essa parte deve ter demorado em torno de 10 horas. Após isto, o novo sistema foi liberado para o pessoal que estava dentro do UOL para a homologação. Foram encontrados alguns problemas (nada sério, ex.: tela de consulta do CEP no cadastro não estava funcionando) que foram corrigidos de forma fácil e rápido. Após essa homologação o sistema foi liberado para os usuários no dia 01/11/2009 às 01:11:11.
Essa reescrita de sistema envolveu desde uma remodelagem completa do banco de dados (também foi trocado de SQLServer para Oracle), troca de linguagem de programação (.Net para Java), e duas coisas críticas: troca de conceitos e de regras de negócio.
A troca de conceitos deve-se ao novo jeito que as transações são vistas no sistema. Antes, cada movimentação de dinheiro (ou movimentação financeira) era feita através de uma nova transação. No novo PagSeguro cada intenção de compra, adição de fundos, etc, cria apenas uma transação, sendo que esta transação pode possuir diversas movimentações financeiras associadas.
Outra mudança grande é a maneira como o saldo é “calculado”. Antes, o sistema recalculava o saldo do usuário à partir dos status das transações. Este jeito era extremamente lento. O novo sistema consolida o saldo do usuário, sendo que sempre que é necessário saber o saldo não é necessário fazer cálculos. Essa é a mesma abordagem utilizada por diversos bancos.
Basicamente, esse projeto (na visão de desenvolvimento) durou aproximadamente 1 ano e 9 meses. Durante esse tempo todo tivemos que resolver diversos problemas, tivemos diversas brigas, diversas alegrias e diversas discussões.
Apesar de tudo: obrigado a todas as pessoas que ajudaram de alguma forma com este projeto e boa sorte pra todos nós!
Agora só falta a cervejada para comemorar!
October 23, 2009
Programação, Python
1 Comment
Para setar a linguagem padrão da sua aplicação utilizando o turbogears basta editar o arquivo development.ini e incluir a seguinte linha após [app:main]:
lang = pt_BR
Depois execute os seguintes comandos:
python setup.py extract_messages
python setup.py init_catalog -l pt_BR
python setup.py compile_catalog
O primeiro comando extrai todas as mensages que devem ser traduzidas (dos templates e dos códigos python). O segundo comando cria um arquivo de tradução para a linguagem pt_BR. Após esse passo, você deve editar o arquivo gerado para traduzir as mensagens. O terceiro comando compila as mensagens traduzidas.
Agora para formatar datas e números no formato da linguagem padrão (ou da linguagem selecionada pelo usuário) basta criar o arquivo lib/i18nHelpers.py:
import tg.i18n
import babel.numbers
import babel.dates
__all__ = ["format_currency", "format_datetime"]
def get_lang(lang):
if lang:
return lang
return tg.i18n.get_lang()[0]
def format_currency(number, currency = "", locale = None, *args, **kargs):
return babel.numbers.format_currency(number, currency, locale = get_lang(locale), *args, **kargs)
def format_datetime(datetime, *args, **kargs):
return babel.dates.format_datetime(datetime, locale = get_lang(locale), *args, **kargs)
E importar essas funções no arquivo lib/helpers.py.
No seu template basta fazer algo assim:
R$ ${h.format_currency(xyz.valor)}
Não mapei todas as funções que o Babel disponibiliza, mas basta fazer como foi feito com essas duas funções.
October 23, 2009
Programação, Python
No Comments
Para se integrar o elixir no turbogears 2, basta editar o arquivo model/__init__.py do seu projeto para ficar desse jeito:
# -*- coding: utf-8 -*-
from zope.sqlalchemy import ZopeTransactionExtension
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base
import elixir
maker = sessionmaker(autoflush=True, autocommit=False,
extension=ZopeTransactionExtension())
DBSession = scoped_session(maker)
elixir.session = DBSession
elixir.options_defaults["shortnames"] = True
DeclarativeBase = declarative_base()
metadata = DeclarativeBase.metadata
elixir.metadata = metadata
def init_model(engine):
"""Call me before using any of the tables or classes in the model."""
DBSession.configure(bind=engine)
from xyz.model.auth import User, Group, Permission
from xyz.model.entidades import Xyz
elixir.setup_all()
E para declarar suas entidades, basta fazer do jeito do Elixir, estendendo a classe elixir.Entity.
Com essa integração conseguimos utilizar o padrão Active Record.
October 14, 2009
Programação, Python
No Comments
Para instalar o setuptools no Python 2.6 no Windows baixe os seguintes arquivos:
- setuptools-0.6c9.tar.gz
- setuptools-0.6c9-py2.6.egg
Estes arquivos estão no site: http://pypi.python.org/pypi/setuptools.
Depois extraia o arquivo setuptools-0.6c9.tar.gz e execute o seguinte comando:
python ez_setup.py setuptools-0.6c9-py2.6.egg
O comando acima irá instalar o setuptools no diretório de instalação do python. Para executar o easy_install basta que no PATH do sistema esteja o diretório Scripts que está dentro da pasta de instalação do Python.
September 23, 2009
Java, Java EE, Programação, Uncategorized
No Comments
Este post foi traduzido e alterado deste link:
http://blog.cherouvim.com/the-stupidest-things-ive-done-in-my-programming-job/
Observação: Não fui eu quem escreveu este post. Apenas fiz a tradução e alteração pois achei muito interessante.
As coisas estúpidas feitas quando se trabalho com programação
- ORM
- Estupidez
Construir um framework próprio de ORM.
- Consequências
O projeto vira uma bagunça depois de 2 anos de manutenção com gambiarras para passar pelo meu framework ORM desenvolvido e chamar comandos SQL’s customizados.
- O que deveria ter sido feito?
Usar hibernate, iBATIS, Cayenne ou outros parecidos.
- EAV
- Estupidez
Usar uma modelagem de banco de dados do tipo Entity-Attribute-Value model.
- Consequências
Solução não escalável e impossibilidade de rodar queries úteis no banco de dados.
- O que deveria ter sido feito?
Usar uma modelagem de banco de dados normalizada.
- Acesso ao Banco de dados
- Estupidez
Sincronizar o acesso ao banco de dados com uma conexão compartilhada.
- Consequências
Escalabilidade zero. Tempos de respostas muito lentos quando mais de 10 usuários estavam utilizando a aplicação.
- O que deveria ter sido feito?
Não fazer isto e utilizar um pool de conexões como c3p0 e usar uma “nova” (reutilizada) conexão retornada do pool para cada ciclo de request / response.
- IDE
- Estupidez
Evitar aprender e utilizar uma IDE.
- Consequências
Falta de habilidade de compilar, testar e fazer o deploy da aplicação rapidamente e / ou geralmente fazer qualquer coisa útil.
- O que deveria ter sido feito?
Familiarizar-me com uma IDE. Ex.: NetBeans, eclipse, etc.
- Transações
- Estupidez
Não usá-las.
- Consequências
Corromper os dados da aplicação.
- O que deveria ter sido feito?
Usar transações do banco de dados. No MySQL usar InnoDB.
- Prepared Statements
- Estupidez
Usar Statements, concatenação de strings e escapar caracteres para montar queries “seguras”.
- Consequências
Possibilidade de SQL Injections na aplicação. É possível logar utilizando por exemplo “or 1=1;delete from users;” e alterar o estado do banco de dados de uma forma muito desagradável.
- O que deveria ter sido feito?
Usar Prepared Statements que montam e escapam corretamente as queries dependendo do driver JDBC utilizado.
- Lógica de Negócios
- Estupidez
Fazer isto nos templates (JSP).
- Consequências
Aplicação de manutenção difícil.
- O que deveria ter sido feito?
Fazer isto utilizando o padrão MVC com servlets ou com um Front Controller. Melhor se utilizar um framework MVC open source como Struts, Spring MVC, etc.
August 30, 2009
Programação
No Comments
Essa semana troquei o repositório svn de um sistema meu do meu desktop para o site http://www.xp-dev.com. Tive que trocar todas as working copies do meu notebook e desktop para referenciar essa nova localização.
Para fazer isso basta utilizar o seguinte comando:
svn sw –relocate <localização antiga> <nova localização>
July 27, 2009
Programação
No Comments
Semana passada no trabalho perdi umas 2 horas com o problema ORA-17410: No more data to read from socket. Em diversos lugares falava que era porque o oracle não estava suportando o modo de conexões compartilhadas. Tentei alterar o oracle para dar o suporte para conexões compartilhadas mas sem sucesso.
Após algumas tentativas, verifiquei que o problema era ocasionado quando fazia um select no banco de dados e esse select utilizava um índice específico. Depois de dropar e recriar o índice este erro parou de acontecer.
July 21, 2009
Java EE
No Comments
Depois de muito tempo consegui fazer minha aplicação utilizando Freemarker (template engine) + Sitemesh (web page layout framework) + Spring (IOC, etc) funcionar.
Basicamente, basta configurar no web.xml o filtro do Sitemesh (com.opensymphony.sitemesh.webapp.SiteMeshFilter), a servlet do Freemarker que vem com o Sitemesh (com.opensymphony.module.sitemesh.freemarker.FreemarkerDecoratorServlet) e a servlet do Spring MVC (org.springframework.web.servlet.DispatcherServlet).
O filtro do Sitemesh é aplicado a todas as requisições, a servlet do freemarker às urls *.ftl e a servlet do Spring às urls *.html.
O problema que eu tive foi que os templates do Freemarker e do Sitemesh não eram encontrados. No web.xml, um dos parâmetros iniciais da servlet do Freemarker é o diretório dos templates (TemplatePath). Configurei este parâmetro para “/WEB-INF/templates/”. E no arquivo decorators.xml configurei que os templates do Sitemesh ficavam no diretório “/decorators”. O que acontecia é que o diretório dos templates do Sitemesh deveriam ficar dentro do diretório dos templates do Freemarker. Logo a estrutura de diretórios é dessa maneira: /WEB-INF/templates/decorators.
Segue abaixo o link com a aplicação de exemplo desta integração:
http://www.fnbrandao.com.br/blog/files/freemarker.tar.gz
December 14, 2008
Java, Programação
1 Comment
Ainda em relação ao post anterior, tive que extrair o conteúdo de um arquivo PDB (um formato de arquivo usado nos Palm’s).
Encontrei a solução parcial neste post:http://www.neowin.net/forum/index.php?s=d21af43a292e783de98d0644c0824b70&showtopic=689476&pid=590047756&st=0&#entry590047756
A solução descrita não funcionou, mas após algumas alterações na solução, serviu para o que eu precisava:
/***
* T3_allfiles
* based upon T3_APR.java from Shadowmite's forum
*
* This file will extract a binary file from it's
* Palm PDB prison. Just drop this in the directory
* that contains the *.pdb files, and run it. It'll
* get them all. Well, mostly. See next.
*
* This file is NOT made to extract the rom image.
* Use Grack's RomTool for that.
*/
import java.io.*;
public class T3_allfiles {
public static void main(String[] args) throws Exception {
File directory = new File(“/home/fabio/Desktop/pdb/”);
String[] files = directory.list(new PDBfilter());
for (String individualFile : files) {
pdb2(“/home/fabio/Desktop/pdb/” + individualFile);
}
}
static void pdb2(String file) throws Exception {
System.out.println(file);
RandomAccessFile in = new RandomAccessFile(file, “r”);
in.skipBytes(76);
int numRec = in.readShort();
int[] toc = new int[numRec];
for (int i = 0; i < numRec; ++i) {
toc[i] = in.readInt();
in.readInt();
}
for (int i = 0; i < numRec; ++i) {
in.seek(toc[i]);
short fileNameSize = in.readShort();
byte[] fn = new byte[fileNameSize];
in.read(fn);
String fileName = new String(fn);
System.out.println(“\t” + fileName);
String[] directories = fileName.split(“\\/”);
String directory = “.”;
for (int j = 0; j < directories.length – 1; j++) {
directory += File.separator + directories[j];
}
new File(directory).mkdirs();
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(fileName));
if (i < toc.length – 2) {
int bytesToRead = toc[i + 1] – toc[i] – fileNameSize – 2;
while (bytesToRead > 0) {
out.write(in.read());
bytesToRead–;
}
} else {
int b;
while ((b = in.read()) > -1) {
out.write(b);
}
}
out.close();
}
}
}
class PDBfilter implements FilenameFilter {
public boolean accept(File dir, String name) {
if (new File(dir, name).isDirectory()) {
return false;
}
name = name.toLowerCase();
return name.endsWith(“.pdb”);
}
}
December 14, 2008
Java, Programação
No Comments
Há algum tempo atrás, peguei um serviço pra fazer no qual o cliente não tinha o código fonte do sistema.
Após alguns dias procurando um descompilador java, achei este:
JD-Gui
Este descompilador é muito bom, devido à diversas features, como por exemplo, poder descompilar um jar inteiro, fazer links entre os arquivos descompilados, etc.
« Previous Entries Next Entries »