[News] Estou blogando para a MoIP Labs!
Esta semana comecei a blogar pela MoIP Labs. O MoIP Labs é um espaço dedicado para desenvolvedores que tem interesse em uma solução de pagamentos integrada sem a necessidade de ficar se preocupando com todas as chatices envolvidas no pagamento online.
O trabalho que irei desenvolver é primariamente de manutenção do blog/portal, suporte à outras mídias sociais atualmente utilizadas (principalmente Facebook e Twitter) e coordenação dos repositórios no Github (se você tiver interesse em contribuir, não deixe de me avisar
. Como atividades secundárias, eu pretendo desenvolver roteiros de tutoriais em vídeo e participar no desenvolvimento de bibliotecas que facilitem a utilização do MoIP pelos desenvolvedores.
Seja você empreendedor ou desenvolvedor, não deixe de visitar o MoIP Labs para saber o que é possível fazer com a nossa plataforma (sem querer puxar saco, mas acho difícil você encontrar algo que a plataforma de pagamentos da MoIP não faça por você
) e não deixe de utilizar nosso fórum caso precise de algum suporte.
Utilizando o Dropbox para hospedar seus repositórios Git — uma abordagem mais segura
Estive dando uma olhada num post do Filipe Saraiva sobre como utilizar o Dropbox para sincronização de repositórios Git. A técnica apresentada por ele é bem interessante e eu gostaria de dar mais algumas dicas com relação ao assunto.
Colocando as mãos na massa
No Git, se você quiser trabalhar com repositórios remotos, provavelmente você irá ver soluções que utilizam http, ssh, o daemon do git ou através de uma pasta no seu disco. É justamente essa a idéia: ter uma pasta no Dropbox, que ao mesmo tempo é local e compartilhada entre vários users e que é um repositório do Git.
O setup desta técnica é bem simples, como mostrado a seguir:
$cd ~/Dropbox/user/projeto.git
$git init --bare #cria um repositório git sem uma área de trabalho
$cd /pasta/para/seu/projeto/
$git init # cria o repo git para seu projeto com a área de trabalho
$git add . && git commit -a -m "Primeiro commit" #faz commit (local) de alguns arquivos
$git remote add origin ~/Dropbox/user/projeto.git #adiciona o repo do DropBox como repo remoto
$git push origin master #envia os commits locais para o repo remoto do DropBox
Nota #1: Eu estou mostrando comandos utilizando o bash (comum em sistemas Unix), mas os mesmos funcionam em no Windows também.
Ter um repositório para cada usuário ajuda a garantir que não haverão conflitos no Dropbox quando mais de uma pessoa fizer um push ao mesmo tempo ou ao fazer uma sincronização de arquivos no Dropbox após um push offline. Se você tiver mais de uma pessoa trabalhando com você no mesmo projeto, você pode fazer o seguinte:
$cd ~/Dropbox/fulano/projeto.git
$git init --bare #cria um repositório git sem uma área de trabalho para Fulano
$cd /pasta/para/seu/projeto/
$git remote add fulano ~/Dropbox/fulano/projeto.git
Prontinho! Agora você tem o seu repo e pode colaborar com Fulano facilmente! Quando Fulano fizer um push e quiser que você pegue as modificações dele, basta fazer o seguinte:
$git checkout -b fulano-fix #cria um branch para receber as alterações de fulano
$git fetch fulano #obtém todas as modificações do remote "fulano"
$git merge fulano/master #faz merge das alterações de fulano com as suas
$git checkout master #volta para o branch master
$git merge fulano-fix # faz o merge no master se tiver tudo certo com as alterações de fulano
Nota #2: o exemplo mostrado acima é bem simples. Dependendo do caso, talvez você queira modificar alguma coisa, resolver algum conflito ou negociar com Fulano antes de colocar as alterações dele no seu branch master.
Nota #3: pra ser curto, estou sendo bem superficial. Se você não conhece muita coisa de Git, eu recomendo que você adquira o excelente vídeo tutorial de Git do Fabio Akita (é bem barato, só R$7,99 — e vale muito cada centavo).
Este modelo parece também com a convenção adotada pelo Github de desenvolvimento distribuído, onde cada usuário tem um repositório e a sincronização dos mesmos é feita via pull requests.
Considerações finais
Este modelo funciona bem com as deficiências do Dropbox: você pode fazer commits e pushes locais mesmo estando offline sem se preocupar muito. Há somente um porém: não há (ou pelo menos eu ainda não vi) uma forma de evitar que outra pessoa faça push no seu repositório sem sua permissão. Neste caso, qualidades como boa comunicação e noção das coisas dentro da sua equipe contam bastante ![]()
Happy coding ![]()
[Dica] Valide e-mail, IP e URLs no PHP sem regex
Eu vejo muita gente utilizando regex (expressão regular) para validar vários tipos de dados, incluindo emails, tipos (boolean, string e int), sanitizar dados (remover caracteres inválidos, por exemplo) no PHP. Este tipo de coisa é um saco para quem não saca muito de regex, mas é possível fazer todas estas validações sem o uso de regex utilizando as funções da família filter:
Há vários outros filtros que você pode experimentar com esta função super útil e nunca mais precisar lembrar daquela regex chata de email ![]()
Happy coding!
[Update]
Esqueci de mencionar: Estas funções estão disponíveis a partir do PHP 5.2.0. Valeu, Almir Mendes!
Google Wave e entrega de software contínua: o que se pode concluir
O Google Wave morreu. Quer dizer, ainda não, mas vai até o fim do ano. Um dos projetos mais “badalados” do Google até pouco tempo depois da sua abertura oficial deixa dois sinais claros: 1) A queda de gigantes na Web pode acontecer de forma muito rápida e 2) Você deve entregar seu software com mais freqüência.
O Google Wave foi anunciado no Google I/O do ano passado e segundo os líderes do projeto, o Google Wave já tinha 2 anos quando foi apresentado ao público pela primeira vez. Dois anos. E isso não foi nem uma entrega, foi um beta super-fechado que o Google fez na conferência.
Houve uma grande corrida para obter novas contas do Google Wave (tinha maluco vendendo conta até no eBay, para se ter noção de quão grande a coisa parecia). Só que este entusiasmo parou nas primeiras semanas de uso do produto. Os principais motivos foram:
- Interface complexa – Muitas funcionalidades em um só lugar, apresentadas de forma “mágica” e que deixaram os usuários confusos
- Lentidão – O Google Wave é super pesado. Quem tinha o Firefox ou o IE não conseguia rodar com uma performance decente. O Chrome e o Safari eram a solução, mas nem todo mundo viam as coisas desta forma.
- Falta de integração com o Gmail (e outros produtos do Google) – Na minha opinião, houve um deslumbramento tão grande com o termo “Email 2.0″ que eles esqueceram do email tradicional e de outras ferramentas populares, que funcionam e que muitas pessoas utilizam.
Os problemas listados acima juntamente com o problema da aceitação do produto poderiam ter sidos resolvidos (ou ao menos amenizados) se o Google fizesse entregas de partes do Wave antes. Como? Eu explico:
- Entrega contínua implica necessariamente em feedback contínuo. A idéia do Wave é genial, mas cada pedacinho dele não pôde ser “devidamente apreciado” pelos seus usuários. Sem contar que à medida que funcionalidades forem sendo lançadas, bugs iriam sendo detectados e corrigidos de forma mais fácil. Agora imagine você corrigindo um bug de um código que você fez há mais dois anos…
- O Google poderia ter mudado o rumo do produto antes, mas mantendo as idéias inovadoras. Que tal ter um chat com timeline no Gmail? E um email com playback? Quem sabe até um email similar a uma Wave onde se pode ver as alterações em tempo real? Tudo isso poderia ter sido acrescentado ao Gmail (e talvez a outros serviços), aumentando muito o nível de satisfação com do usuário
- Compatibilidade de plataformas. Somados, o IE e o Firefox detêm mais de 70% do mercado de navegadores. 70%. E o Wave não funciona tão rápido nestes navegadores quanto ele funciona no Google Chrome ou Safari. Com entregas curtas, o Google poderia ir “sugerindo” a migração para outros navegadores e/ou adaptando o Wave para funcionar melhor com browsers mais lentos.
Concluindo: Entregue seu software com mais frequencia. Você diminui os riscos e deixa seus clientes e usuários mais satisfeitos.
Quando uma deficiência pode se tornar uma feature numa linguagem de programação
Estava lendo um antigo post do Obie Fernandez onde ele lista várias razões do porquê Java é uma porcaria (em tom de brincadeira, claro =). Numa das razões citadas por ele, há o seguinte trecho:
8 ) Java has good debugging support
Java has great and powerful debugging (which is very necessary since most Java code sucks so much ass). Ruby has ridiculously pitiful debugging support, which means our code actually needs to be well-tested and readable.
Traduzindo:
8 ) Java possui um bom suporte a debugging
Java possui um excelente e poderoso debugging (o que é necessário, já que boa parte de códigos em Java são muito ruins). Ruby tem um suporte a debugging lamentavelmente ridículo, o que significa que nosso código realmente precisa ser bem testado e legível.
Vendo por este lado, Ruby é uma excelente linguagem para quem sabe fazer direito e uma droga pra quem está acostumado com IDEs com Intellisense e checagem de erros pelo compilador.
Outras linguagens possuem problemas que são resolvidos facilmente com o uso de testes unitários. Um problema clássico que acontece com o PHP, o White Screen of Death (um erro que acontece com o script que nenhuma informação ou mensagem de erro é apresentada), pode ser resolvido com o uso de testes.
Alguns “problemas” advindos com linguagens dinâmicas é com a mudança de tipo de uma determinada variável, por exemplo:
x = 1
y = 3
def soma(self):
return self.x + self.y
op = Op()
op.y = "aha!"
op.soma() #Ooopss... TypeError
Este é um tipo de problema que vem com a checagem de tipo em tempo de execução, ao invés de ser feito em tempo de compilação. Muitas pessoas que não possuem a mesma visão do Obie, encaram isto como um problema.
Opinionated Software
Um trecho muito conhecido do Getting Real é o trecho que fala sobre opinionated software:
Your app should take sides
Some people argue software should be agnostic. They say it’s arrogant for developers to limit features or ignore feature requests. They say software should always be as flexible as possible.
We think that’s bullshit. The best software has a vision. The best software takes sides. When someone uses software, they’re not just looking for features, they’re looking for an approach. They’re looking for a vision. Decide what your vision is and run with it.
Traduzindo:
Seu aplicativo deve tomar partido
Algumas pessoas defendem que o software deve ser agnóstico. Dizem que é arrogante da parte dos desenvolvedores limitar a funcionalidade ou ignorar pedidos de novos recursos. Dizem que o software deve ser sempre o mais flexível possível.
Para nós isso é papo-furado. O melhor software traz consigo uma visão. O melhor software toma partido. Quando alguém usa um software, não está procurando apenas recursos, está procurando uma abordagem. Está procurando uma visão. Decida qual é sua visão e atenha-se a ela.
Esta mesma idéia permeia linguagens de programação. Você não achará um linguagem que sirva bem para todos os tipos de casos. Python, por exemplo, não é uma boa linguagem se você quiser usar threads pesadamente. Erlang, apesar de ser uma excelente escolha para programação distribuída e paralela, enfrenta um certo preconceito por ser funcional e não ter suporte à orientação a objetos. C#.NET é uma boa linguagem para criação de aplicativos comerciais, mas não é totalmente portável para todas as plataformas (o Mono mal suporta o .NET 3.5 e o framework já está na versão 4).
Conclusão: antes de reclamar de uma linguagem de programação, saiba que toda linguagem tem um approach, um foco e veja se esta “falha” pode ser algo útil… muitas vezes o é ![]()
[jQuery para apressados] Modularizando sua aplicação com Module Pattern e jQuery
O module pattern é um padrão de projetos para JavaScript que permite que você use closures autoexecutáveis para criação de “classes” com “atributos privados”.
Calma que eu explico :0)
O JavaScript não possui meios de declarar uma variável como “protected” ou “private”, como você costuma ver em linguagens como Java, C# e C++. Como uma forma de “proteger” alguns objetos de acesso externo, desenvolveu-se uma técnica chamada “module pattern”, que tem o poder de encapsular e restringir o acesso a tais objetos.
Antes de irmos para o module pattern, de uma olhada numa função autoexecutável:
alert('olá, mundo!');
}) ();
Interessante, não? Eu estou criando uma função e executando-a ao mesmo tempo. Note que eu posso passar um parâmetro pra ela se for necessário:
alert('Olá, '+nome+'!'); // Olá, Herberth
}) ('Herberth');
O module pattern funciona do mesmo jeito:
var itens = []; // variável "privada". Não pode ser acessada externamente
function hasItem(item)
{
return jQuery.inArray(item,itens)!=-1;
}
function addItem(item)
{
if(!hasItem(item))
{
itens.push(item);
}
else
{
alert('Opa! O item '+item+' já está selecionado');
}
}
function removeItem(item)
{
var position = jQuery.inArray(item,itens);
if(hasItem(item))
{
delete itens[position];
}
else
alert('Opa, não temos o item '+item+' no carrinho de compras')
}
// retorna um objeto com o que será visível pro mundo
// note que o array itens não está incluído
return {removeItem:removeItem,addItem:addItem};
})();
//poderíamos utilizar o código acima da seguinte forma:
CarrinhoDeCompras.addItem('Livro');
CarrinhoDeCompras.addItem('Caneca');
CarrinhoDeCompras.addItem('Livro'); //Opa, o item Livro já está adicionado
CarrinhoDeCompras.removeItem('Livro'); // remove ok
CarrinhoDeCompras.removeItem('Livro'); // Opa, não temos o item Livro no carrinho de compras
// mas não poderiámos fazer algo assim:
CarrinhoDeCompras.itens.push('Camiseta');
Neste caso, eu estou retornando um objeto contendo a referências das funções que eu declarei dentro da minha função autoexecutável. Perceba que, em hipótese alguma, eu conseguiria acessar diretamente o conteúdo/valor do array itens, pois eu não tenho uma referência dele externamente.
Isto é algo importante, por dois motivos:
- Se você estiver num time de desenvolvimento e desenvolver um módulo utilizando o module pattern, o desenvolvedor que pegar o seu módulo para utilizar saberá o que ele pode e o que não pode acessar.
- Você previne que aquele engraçadinho que sabe usar o Firebug mexa nos seus objetos em tempo de execução.
Onde o jQuery entra nesta história?
O jQuery entra principalmente na parte em que começamos a trabalhar com eventos customizados. Estes eventos customizados podem funcionar como um meio de comunicação entre os módulos da aplicação, sem que um conheça necessariamente o outro. O que é necessário que cada módulo saiba é como utilizar os eventos.
Continuando o exemplo anterior:
var itens = []; // variável "privada". Não pode ser acessada externamente
function hasItem(item)
{
return jQuery.inArray(item,itens)!=-1;
}
function addItem(item)
{
if(!hasItem(item))
{
itens.push(item);
}
else
{
alert('Opa! O item '+item+' já está selecionado');
}
}
function removeItem(item)
{
var position = jQuery.inArray(item,itens);
if(hasItem(item))
{
delete itens[position];
}
else
alert('Opa, não temos o item '+item+' no carrinho de compras')
}
function finalizarCompras()
{
// dispara o evento "finalizaCompras"
// quem estiver "ouvindo" este evento, receberá os itens como argumento
$(document).trigger("finalizaCompras",itens);
}
function init() { } // algum código de inicialização
// retorna um objeto com o que será visível pro mundo
// note que o array itens não está incluído
return {removeItem:removeItem,addItem:addItem,init:init};
})();
var Services = (function(){
function finalizarCompras(event,itens) // função "privada". Não pode ser acessada externamente
{
// envia os itens por AJAX e faz algum tratamento.
}
function init()
{
// "escuta" pelo evento finalizaCompras
// quando o mesmo for disparado, a função finalizarCompras será executada
// com os parâmetros do evento
$(document).bind("finalizaCompras",finalizarCompras);
}
return {init:init};
})();
$(document).ready(function(){
//inicializamos os módulos e colocamos os manipuladores de eventos.
CarrinhoDeCompras.init();
Services.init();
});
Whoa! Conseguimos desacoplar nossa aplicação utilizando eventos customizados.
Um módulo não conhece o outro, mas os mesmos se comunicam através de eventos. Note que a única coisa comum entre os módulos é o nome do evento utilizado para finalizar a compra.
Fazendo um paralelo com Programação Orientada a Objetos, os eventos seriam nossa Interface, neste caso.
Seria possível ainda, o módulo Service disparar um evento para avisar o CarrinhoDeCompras quando a transação for completada.
Interessante, não? ![]()



