HTML5: Problemas com Input type=”number”

Opa, esse é mais um aviso.

Recentemente estava trabalhando em um sistema com CakePHP 2.1 e ao tentar editar um registro onde um dos campos era do tipo float, o valor que estava no banco não era apresentado no formulário, embora a tag input estivesse com o atributo value preenchido corretamente. Isso aconteceu comigo no Chrome 17, no Firefox 10 não houve problema porque ele utiliza input text normal.

Um detalhe importante é que eu utilizo o Helper Locale para formatar os números decimais para meus usuários, assim o que vem do banco como “12.58” vira “12,58” formato que usamos no Brasil. Talvez se usasse ponto como separador de decimais não teria problema – o que não é possível pra mim.

Ao pesquisar um pouco descobri um bug no Chromium relacionado a isso reportado no link http://code.google.com/p/chromium/issues/detail?id=44116 . Não consegui entender o motivo mas foi marcado como Wontfix.

A saída foi sobrescrever o FormHelper para utilizar input do tipo text quando o número vindo é um ponto flutuante/decimal. Se você não trabalha com CakePHP, mas trabalha com números decimais separados por vírgula, a dica continua valendo: utilize input com o tipo text ao invés de number.

Aqui tem um commit onde implementamos a “correção” em um FormHelper que estende o do CakePHP.

[CakePHP] Dica Rápida – Usando shell de múltiplas versões

Tirando a poeira disso aqui…

Desde que comecei com CakePHP me sentia frustrado por não conseguir utilizar o shell de diferentes versões sem precisar alterar meu ambiente de trabalho. Na época meu problema era ter projetos rodando a versão 1.2 e outros rodando 1.3.

Ontem me deparei novamente com o problema e cheguei até a sugerir um alias embutido no CakePHP, porém a ideia foi sabiamente rejeitada.

A solução para isso é mais simples do que parece (se você usa Linux e Bash, pelo menos): basta criar uma alias de comando para cada uma das versões do CakePHP.

Como fazer

  1. Abra o arquivo ~/.bashrc (se não existir, crie-o);
  2. Para cada versão do CakePHP você vai criar um alias seguindo este “template”:
alias cake13="~/pastas_ate_chegar_ao_cake/cakephp/cake/console/cake"

Meu arquivo ficou assim:

alias cake13="~/develop/php/cake13/cake/console/cake"
alias cake2="~/develop/php/cake2/lib/Cake/Console/cake"

Agora é só fechar e abrir novamente o terminal e usar os comandos “cake2”, “cake13” ou outro que você tenha criado. Works like a charm ;]

Aplicações heterogêneas e a busca por conhecimento

Estive muito tempo sem escrever neste espaço por dois motivos: falta de tempo hábil e de um tema “supimpa”, que não fosse o mesmo abordado milhões de vezes por milhões de outros blogs.

Felizmente a falta de tempo ainda é um problema, graças aos trabalhos na Radig. Digo felizmente por que é muito bom trabalhar no que você gosta, com grandes amigos e possibilidades infinitas. Mas agora os assuntos estão fervilhando na minha cabeça.

Hoje quero falar um pouco de aplicações heterogêneas. Não sei nem se o termo é utilizado, busquei  no oráculo e não encontrei referências, tentei por sistemas heterogêneos mas o que vem são informações sobre química e soluções heterogêneas.

Mas se o termo não existe, o que quero dizer com aplicações heterogêneas? São aplicações que mesclam tecnologias diferentes com um mesmo propósito, por exemplo: uso de dois modelos de SGDB’s ou duas linguagens de programação server-side, mas que compartilham informações de modo altamente acoplado.

Venho trabalhando em alguns produtos (um deles é o Juris, conhece?) e um dos recursos que implementamos são notificações em tempo real sobre ações dentro do sistema para os usuários de interesse.

No projeto do sistema de notificações nós tínhamos os requisitos:

  • Baixo tempo de resposta entre a ação e o disparo de notificação
  • Escalabilidade – suportar, sem sobrecarregar o servidor, mais de 1000 conexões simultâneas
  • Fácil manutenção
  • Independência do sistema – acoplamento baixo em código, mas alto em relação aos dados

Nossos principais sistemas foram desenvolvidos em PHP, portanto parecia natural escolher a triad PHP+APACHE+(MySQL/PostgreSQL) para o sistema de notificação. Parecia.

Em abril deste ano tive a felicidade de participar do evento BrazilJS, onde pude ver feras como Mike Taylor, Richard Worth e seu irmão* Guilherme Chapiewski, o lendário Maujor, os gaúchos Jaydson e Felipe Nascimento que organizaram um evento do outro lado do país, o Ricardo Coelho – segundo maranhense mais conhecido e influente do país (perde só para nosso querido² Sarney) além do velho conhecido PorKaria.

Duas coisas realmente me chamaram atenção durante o evento: o extensivo uso que tem sido feito da linguagem JavaScript para rodar aplicações no servidor, através do Node.js, e a possibilidade de criação de aplicações com resposta em tempo real com baixo custo computacional através de bibliotecas como Socket.io e PubSub.io ou mesmo protocolos adicionados aos browsers recentes como o websocket.

Estes dois ingredientes (JavaScript no servidor + Websocket) atenderiam perfeitamente os requisitos de minhas aplicações. E a escolha foi feita. Desenvolvi, com poucas linhas de código, toda a aplicação, porém uma parte ficou nebulosa: como compartilhar as notificações geradas em um sistema com outra aplicação? E como saber se a pessoa que está conectada ao servidor de notificações é realmente o usuário autorizado a acessar o sistema? A resposta que encontrei foi compartilhar as sessões.

Como fiz isso? Armazenando a sessão do sistema principal em um banco de dados (escolhi para isso o MongoDB, pela velocidade e escalabilidade), enquanto no servidor de notificação só acesso as sessões disponíveis no banco e verifico se o usuário que tenta acessar notificações está realmente autenticado.

Para implementar isso foi preciso um pouco de pesquisa e adaptação tanto no servidor de notificações quanto no sistema principal, mas os detalhes deixarei para uma próxima oportunidade.

Quero deixar registrado aqui meu tardio parabéns a organização e aos palestrantes do BrazilJS, o evento foi sensacional.
E que o texto sirva de inspiração para aqueles que acreditam na “bala de prata” (ela não existe).
Não deixe de participar de eventos, comunidades ou fóruns. Nunca pare de estudar, algo que era uma boa solução à 1 ano hoje pode ser uma péssima alternativa perto das demais.

* Piada interna do evento.
² – [/sarcasm]

Mantendo uma base de código organizada e documentada

Uma problemática comum de quem desenvolve sistemas é como manter a documentação em dia, se que isso comprometa os prazos de desenvolvimento.

Digamos que isso é um problema de otimização:

  1. um código bem documentado facilita e muito a sua manutenção;
  2. documentar código leva tempo;
  3. tempo é um recurso escasso em desenvolvimento de software;

Olha o problema… sem tempo, não há documentação e sem documentação você precisará de mais tempo para dar manutenção – oras, mas você já não tinha tempo para documentar, como vai ter mais tempo agora para dar manutenção?

Tentando equacionar esse problema surgiram várias ferramentas que visam facilitar todas as atividades relacionadas ao desenvolvimento.

Como a maior parte do meu tempo dedico ao PHP e CakePHP, tomarei estes como base para as ferramentas, porém várias delas podem ser utilizadas com outras linguagens/frameworks sem grandes problemas ou então possuem similares em outras linguagens.

Padrão de código

A primeira etapa, e talvez a mais importante, seja definir e disponibilizar um conjunto de regras explicando como o código foi escrito.

Este padrão envolve nome de classes, atributos, métodos, comentários, tabelas e colunas do banco de dados, organização de diretórios dentre outras coisas. Até coisas simples como a indentação deve ser padronizada.

Veja alguns guias de codificação para ter um exemplo do que quero dizer:

Versionamento de código

Um dos recursos mais importantes durante o desenvolvimento é a capacidade de se desfazer determinada alteração e manter um registro de todas as alterações feitas durante o desenvolvimento.

Atualmente, minha ferramenta favorita para versionamento é o Git um sistema distribuído de controle de versão. Porém existem vários outros que podem agradar, como o centralizador SVN e os também distribuídos Mercurial e Bazaar.

É muito fácil trabalhar com qualquer um destes sistemas e após conhecer as facilidades que o versionamento de código lhe proporcionam, você terá dificuldade em trabalhar com código sem controle de versão, pode apostar.

Caso você opte por um sistema distribuído, dê uma olhada neste modelo de organização para seu código: A successful Git branch model

Versionamento do Banco de Dados

Por melhor que seja o projeto do seu sistema uma coisa sempre ocorrerá: mudança. E isso envolve mais do que código, muitas vezes alterações na estrutura do banco são necessárias.

Como controlar essas alterações? A resposta é “Migrations”

No CakePHP precisamos de plugins para dar essa capacidade a aplicação, há dois largamente utilizados:

Outros frameworks fornecem suporte “nativo” ao recurso, como o Ruby on Rails e Doctrine para PHP em geral.

Testes unitários

Acredito que todos os frameworks modernos fornecem suporte a criação de testes unitários em seus projetos. Os testes são uma fase importante do design do software e fundamental para documentação de qualidade.

O CakePHP até sua versão 1.3 utiliza o framework de testes SimpleTest, porém passará a utilizar o PHPUnit em sua versão 2.0 (atualmente em desenvolvimento).

Não sabe o que são testes unitários? Bom, segue alguns links sobre o assunto:

Testes são como controle de versão… depois que você usa, não vive sem.

Documentação

Como comentado anteriormente, um passo importante para documentação são os testes unitários. Porém não devem ser o único.

Uma forma muito eficiente de documentação são os blocos de comentários, no PHP, o padrão PHPDoc é o mais utilizado.

Existem várias ferramentas que varrem o código de sua aplicação e identificam esses blocos para gerar a documentação, alguns deles são:

Quando sua documentação é concisa e completa, entender o funcionamento da aplicação passa a ser fácil, independente de quando ela foi criada. Quando isso é aliado aos testes unitários, fazer manutenção passa a ser uma atividade mais fácil e gratificante.

Por fim, é preciso saber o que/quando está errado e como/quando foi corrigido, ajudando na manutenção do histórico e acompanhamento da evolução do software. Para isso temos o tópico a seguir.

Controle de Bugs/Atividades

Como controlar o que, quando e por quem uma determinada atividade deve ser feita? E como verificar por quem e quando determinada funcionalidade foi implementada? O controle de versão pode fornecer parte destas respostas, mas ficar analisando logs normalmente não é muito comodo. A melhor maneira é utilizar uma ferramenta de controle de bugs/atividades.

Utilizo no meu dia-a-dia o excelente Redmine, um sistema simples porém poderoso para controle de tarefas. Suporta diferentes projetos, sub-projetos, integra-se com vários sistemas de versionamento de código, permite criação de wikis para documentação além de vários outros recursos.

Além deste, existem vários outros sistemas como o Bugzilla, Trac, Mantis e PHProjekt.

Conclusão?

Não, não tem conclusão. O texto visa apenas apresentar algumas atividades que juntas ao planejamento e desenvolvimento de software tendem a tornar a vida dos desenvolvedores melhor, seja diminuindo o stress causado por alterações dos requisitos ou manutenção de código mal projetado/escrito, seja tornando o desenvolvimento mais ágil, permitindo mais horas de lazer e descanso e menos fios de cabelo branco.

A intenção nunca foi cobrir todos os tópicos a exaustão, mas sim apresentar alguns exemplos e motivos para adoção de tais ferramentas/ideias. Caso tenha surgido dúvida a respeito de qualquer item, deixe um comentário =]

Sentiu a falta de algum item? Utiliza algo de forma diferente? Deixe um comentário também.

————-
Postado originalmente no blog da Radig

Dica Rápida – Evitando problemas com uso de jQuery e imagens

Algumas vezes precisamos recuperar, em tempo de execução, o tamanho de uma determinada imagem para aplica-la corretamente ao layout da página, porém essa verificação pode acontecer antes da hora, o que geraria erros inesperados.

Todo mundo que trabalha com a biblioteca jQuery conhece a chamada:

$(document).ready({
//seu código javascript
});

Ela diz ao browser para executar o bloco interno somente quando o DOM do seu documento tiver sido totalmente carregado, isso permite que ele faça o parser de seu documento utilizando os seletores sem esquecer de nenhum item. Porém quando carregamos estruturas externas ao DOM, como uma imagem, não temos garantia de que o código dentro do bloco anterior será executado quando a imagem já tiver sido carregada.
Dessa maneira, caso você precise de informações sobre a imagem, seu script falhará.

Para contornar isso, podemos utilizar uma outra chamada, que é disparada somente quando TODO o documento tiver sido carregado:

$(window).load({
//seu código javascript
});

As duas diferenças, além do comportamento são:

  1. Saí o ‘seletor’ document para a entrada do window;
  2. Saí o evento ready para a entrada do load;

A primeira alteração ocorre por conta da segunda, já que o evento load não pode ser associado a um document.

Com essa pequena alteração você garante que seu script rodará apenas quando todo o documento tiver sido carregado – o que é essencial em algumas situações, como a citada anteriormente, porém dispensável na maioria das vezes.

Fonte: http://api.jquery.com/load-event/

[Comitiva] Como utilizar controle de permissão no sistema – quase tudo mudou

No último post falei um pouco sobre o sistema de permissões que implantamos no Comitiva.

Acontece que após a adição de uma nova funcionalidade (submissão de trabalhos) aquele sistema de permissão começou a ficar ineficiente, e apesar de eu ter dito nos comentários que o ideal era implementar o Acl para este controle no sistema, acabei por implementar a solução sugerida pelo grande Humberto – que, tomando como ponto inicial o que tínhamos, era o jeito mais simples de solucionar os problemas.

Então o que mudou?

  • Os usuários não possuem mais um “tipo”, agora eles pertencem a “grupos” (um ou mais);
  • A verificação de permissão é feita na classe AppController, de forma genérica, o que elimina a necessidade de reescrever a função de autorização a cada controlador;
  • Os grupos que um usuário pertence ficam definidos em um campo “groups”, do tipo varchar e são guardados codificados no formato json
  • Defini um método protegido no AppController para verificar se o usuário logado pertence a um grupo qualquer, facilitando essa operação quando necessário. (o método chama-se AppController::__checkGroup($string) )

O que não mudou?

  • As ações continuam tendo como prefixo o grupo que pode acessa-la, sendo assim, a ação ProposalsController::participant_add() está disponível a todos os usuários que pertençam ao grupo “participant”
  • Todos os usuários registrados pertencem inicialmente ao grupo ‘participant’, porém podem vir a pertencer a outros grupos posteriormente (em adição ao grupo ‘participant’)
  • Continua sendo muito fácil saber se o  usuário logado pode ou não efetuar uma ação, basta usar o método supracitado __checkGroup.

Exemplo de como verificar se o usuário é administrador

if($this->__checkGroup('admin'))
    echo 'O usuário logado é administrador';
else
    echo 'O usuário logado não é administrador';

[Comitiva] Como utilizar controle de permissão no sistema

Como escrevi anteriormente, o PHPMS mantém um sistema para gerenciar eventos – desde a divulgação de informações, cadastro de eventos, inscrições, pagamentos, envio de mensagens para inscritos e check-in.

Mas o objetivo deste post não é dizer o que já foi dito, quero iniciar uma série de posts onde vou explicar o funcionamento de alguns recursos dentro do Comitiva, convidando todos os desenvolvedores a opinar sobre implementação e contribuir com o projeto.

O assunto de hoje é controle de acesso, então vamos ao que interessa.

Como funciona o controle de acesso no Comitiva?

Utilizamos o componente Auth do CakePHP para cuidar da autenticação (efetuar login, verificar se o usuário está logado e efetuar logout).
Mas precisávamos ir um pouco além da configuração básica, definindo diferentes opções para diferentes tipos de usuários. Para isso, consideramos duas opções iniciais: usar também o Acl Behavior ou ficar apenas com o AuthComponent e criar diferentes actions para diferentes tipos de usuários.

Como possuímos apenas dois tipos de usuários (admin e participant) decidimos pela que seria mais simples inicialmente – mesmo sabendo que a manutenção no futuro poderia ser mais complicada – que foi criar diferentes actions para os tipos de usuários.

Para criar essa funcionalidade, definimos inicialmente um prefixo para cada tipo de usuário (prefixos ‘admin‘ e ‘participant‘). Em seguida configuramos o AuthComponent desta maneira (código extraído do AppController):

//Configure AuthComponent
$this->Auth->authorize = 'controller';
 
if( !isset($this->params['prefix']) || !( in_array($this->params['prefix'], Configure::read('Routing.prefixes')) ) )
{
	// all non-prefixed actions are allowed
	$this->Auth->allow('*');
}

Ou seja, toda ação que não tiver prefixo ou o prefixo não estiver definido nas configurações de rota serão públicas (assim é possível, por exemplo, deixar uma página com instruções acessível à qualquer usuário).

Mas como fica essa verificação de tipos no controlador? Como definimos o método de autorização do Auth como ‘controller’, precisamos definir em todos os controladores o método isAuthorized que deve retornar true quando o acesso é aprovado e false caso contrário.
Seguindo a ideia de que cada tipo de usuário possui um prefixo próprio nas ações, nosso método isAuthorized fica desta forma:

if($this->userLogged == TRUE && $this->params['prefix'] == User::get('type'))
{
	return true;
}
 
return false;

Onde o atributo $this->userLogged pertence a classe AppController e sua função é reduzir chamada ao método $Auth->login() e na segunda parte da condição temos uma comparação entre o prefixo da url acessada e o tipo do usuário – se ambos forem iguais, então o acesso está liberado.

Por fim, devemos criar nossas ações para cada tipo de usuário, onde o prefixo será usado para validar o acesso à aquela ação, veja o exemplo da ação “listar pagamentos”:

// ação exclusiva para admin - tem acesso aos pagamentos de todos os outros usuários
public function admin_index($event_id = null)
{
	$this->Subscription->recursive = 0;
 
	if(is_numeric($event_id))
	{
		$this->paginate = array(
			'conditions' => array(
				'event_id' => $event_id
			)
		);
	}
 
	$this->set(compact('event_id'));
	$this->set('subscriptions', $this->paginate());
}
 
// ação exclusiva para participant - tem acesso somente aos próprios pagamentos
public function participant_index()
{
	$this->Subscription->recursive = 0;
	$this->set('subscriptions', $this->paginate(array('user_id' => User::get('id'))));
}

Como podem ver, isso permite a criação de diferentes regras de negócio para os diferentes tipos de usuários e embora aumente a quantidade de código “redundante” por repetir alguns procedimentos para todos os tipos de usuários, a leitura e entendimento do código é facilitada – basta ver o prefixo do método (ação) para saber quem terá acesso a ele.

Delivery Fácil – Pedir comida na internet é muito fácil

Há mais ou menos três semanas foi lançado um novo serviço para o pessoal de Campo Grande/MS, o Delivery Fácil. Através dele você pode conferir o cardápio de diversos estabelecimentos em Campo Grande que fazem entrega de comida e pedir seu prato pelo próprio site – simples assim.
Você não se preocupa com telefone ocupado, não precisa ficar perguntando o que tem no cardápio, quanto custa cada prato nem se atendem em sua região.
Além disso, todo pedido realizado pelo sistema te da pontos para trocar por prêmios.

No lado do restaurante, o serviço cria mais um canal de venda sem a necessidade de se investir um grande volume de dinheiro para criar um e-commerce.

O serviço é resultado de uma parceria entre a Radig (onde tenho prazer em trabalhar) e dois grandes amigos, Samuel e Habib.

Banner de divulgação do Delivery FácilFaça uma visita, cadastre-se e peça sua comida preferida com todo o conforto que a internet lhe oferece.

Não deixe de seguir o Delivery Fácil no twitter para acompanhar as novidades e promoções que realizarmos: @deliveryfacil

Obrigado pelos peixes SVN

Há alguns anos descobri o fantástico mundo do controle de versão, naquele momento me perguntei “como vivi sem isso até hoje?”. Dali em diante podia alterar arquivos sem medo, qualquer erro era só voltar uma versão e tudo certo. Trabalhar em equipe finalmente se tornava algo fácil, graças ao Subversion – SVN.

Porém os anos passaram e algumas coisas começaram a fazer falta: como faço quando estou desenvolvendo algo grande, fico sem commitar até ter algo estável/usável? crio um branch para isso? mas e depois para unir os branches, e os conflitos? além disso, se só eu estou trabalhando em cima disso, porque commitar para todo mundo algo não pronto?

Foi aí que descobri o GIT, um sistema de controle de versão distribuído, open source e gratuito. Ok, ele é gratuito e open source, mas isso não é motivo suficiente. Como disse, ele é um sistema de controle de versão distribuído, isso quer dizer que cada um que tem uma cópia do repositório tem de fato uma cópia dele, e pode servir outras pessoas, ver histórico, tudo localmente.

Então de quebra, ele resolve o problema de ter de criar um branch para desenvolver uma funcionalidade que só eu vou mexer, posso controlar cada alteração minha localmente, e quando quiser – se quiser – posso sincronizar meu repositório local com um outro central (que eu considero central, já que essa figura não existe no GIT). E mais, ele é MUITO RÁPIDO. Acho que para ajudar na argumentação de que é rápido basta dizer que ele foi feito por alguns desenvolvedores do Kernel Linux, e gerencia todo o código trabalhado por eles – e não é pouca coisa.

Ainda estou caminhando com o GIT, tenho aproveitado minha ânsia de aprende-lo junto com a de contribuir com softwares open source para criar e disponibilizar projetos no GitHub.

A grande maioria dos projetos é voltado ao CakePHP, mas há outras coisas também. Alguns projetos que podem interessar são:

  • Comitiva – Sistema construído em CakePHP 1.3 para gerenciamento de eventos;
  • Plugin Mailer – Um plugin que ajuda na utilização da biblioteca PHP SwiftMailer dentro do CakePHP;
  • Behavior Locale – Um behavior para transformar dados vindo do usuário de seu padrão local para um padrão internacional (de banco de dados)
  • Libs – uma coleção de pequenos scripts PHP que fui fazendo ao longo da vida. Há coisas boas, coisas úteis, coisas não tão úteis, mas tudo pode ser usado ao menos como ponto inicial para uma implementação mais elaborada.

Dica Rápida – CakePHP 1.3, link com prefixo

Quando estávamos criando o Comitiva, decidimos utilizar o novo recurso do CakePHP que permite definir diferentes prefixos.

Em nosso caso, cada prefixo representa um tipo de usuário.

A ideia ia bem, até termos que criar um link explicitando uma rota.

Por padrão, a classe Router reconhece o prefixo em uso no momento e adiciona ele na url que você está construindo, desta forma se eu estiver acessando um endereço http://comitiva/participant/events  e quiser criar um link para a url http://comitiva/admin/users  eu terei um problema (não documentado): a segunda url ficaria http://comitiva/partipant/users , por causa da página que está ativa no momento.

A solução foi me apresentada no IRC, canal #cakephp-pt pelo padeiro Danielpk: adicione um índice com o nome do prefixo associado ao valor TRUE no array de endereço.  Fica algo assim:

$this->Html->link('Administre os usuários', array('controller' => 'users', 'action' => 'index', 'admin' => true));
// ou, caso queira forçar o prefixo participant
$this->Html->link('Veja os usuários', array('controller' => 'users', 'action' => 'index', 'participant' => true));