CakePHP: Construindo relatórios com ReportHelper

Posted by Alberto Leal on August 3rd, 2009

Foi no final do ano passado, se não me engano, que desenvolvi um helper para ser utilizado em projetos PHP que utilizam um framework chamado CakePHP. Utilizei este framework em muitos projetos, tanto em projetos internos da minha empresa quanto para clientes.

Resolvi chamá-lo de “ReportHelper“. Como o próprio nome já diz, um helper para ajudar na criação de relatórios =)

Desde a sua criação, outro desenvolvedor - Carlos Spineli - resolveu dar umas tapas no código para melhorá-lo. Resolvi compartilhar com a comunidade este helper. Ele já está disponível na minha páginal pessoal no Github, e você consegue acessá-lo aqui. Lá você encontrará o código, bem como uma aplicação exemplo que eu criei no screencast que você pode conferir aí embaixo:

ReportHelper - CakePHP from Alberto on Vimeo.

Mandem suas críticas e sugestões.

E, colaborem =)

Git: Recuperando arquivo em commits antigos

Posted by Alberto Leal on July 1st, 2009

Hoje vou dar uma dica rápida de como recuperar um arquivo em commits anteriores.
Cenário: Você está trabalhando em um arquivo e adicionou ele em alguns commit. Mas, depois de alguns minutos, você percebe que as mudanças que você está fazendo estão incorretas, e necessita recuperar a versão que você havia adicionado no commit anterior. Como fazer isso? Vamos ver:

1
2
3
4
5
6
7
8
9
$ touch abc.txt
$ vim abc.txt
$ git add abc.txt
$ git commmit -m 'Abc file'
$ vim abc.txt
$ git add abc.txt
$ git commmit -m 'Some changes'
$ cat abc.txt
$ git checkout HEAD^1 -- abc.txt

O comando é ‘git checkout HEAD^1 — abc.txt’,  onde o número 1 representa a quantidade de commits abaixo, a partir do HEAD, e abc.txt representa o nome do arquivo que você deseja recuperar.

Simples e bastante útil!

Design Pattern: Implementando o Decorator

Posted by Alberto Leal on June 23rd, 2009

Photo: http://static.howstuffworks.com/gif/teen-bedroom-decorating-ideas-2.jpg

O último livro que terminei de ler era sobre Design Pattern. Então, resolvi fazer alguns posts contendo algumas implementações. O padrão de projeto da vez é o Decorator.

——–

O poder da composição

Têm quem ame, e têm quem odeie herança. Existem casos que não há como fugir da herança, mas, sempre que possível, prefira composição a herança. Quando utilizamos herança em uma parte da nossa aplicação, e alguns comportamentos são herdados, estes  são definidos estaticamente em tempo de compilação. Por outro lado, se você estender o comportamento de um objeto por meio de composição, você consegue fazer isso dinamicamente, ou seja, consegue compôr os objetos de forma dinâmica. Com isso, se torna fácil adicionar novas funcionalidades escrevendo um código novo ao invés de alterar o código existente. Isso é bacana, pois o comportamento anterior não é modificado, assim as chances de introdução de erros no código que já estava funcionando é menor. Se algo der errado, basta remover a nova classe que foi criada, por exemplo. Resumindo, mantenha as classes abertas para extensão e fechadas para alteração.

O padrão de projeto decorator anexa novas responsabilidades em um objeto dinamicamente, utilizando  do poder da composição.

Vamos ver como isso funciona na prática. O exemplo que lhe será apresentado é a construção de uma pizza. No momento do pedido, o cliente poderá pedir ao Pizzaiolo que adicione  novos ingredientes na pizza, tais como: orégano e tomate. Exemplo simples e direto, apenas para ilustrar.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package br.eti.albertoleal.decorator;
 
public abstract class Pizza {
 
private String description = "Unknown Pizza";
 
public void setDescription(String desc) {
description = desc;
}
 
public String getDescription(){
return description;
}
 
public abstract double cost();
 
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package br.eti.albertoleal.decorator;
 
public class Cheese extends Pizza {
 
	public Cheese(){
		setDescription("Cheese Pizza")
	}
 
	@Override
	public double cost() {
		return 19.90;
	}
 
}

As classes decorator devem ser espelhos das classes que elas vão decorar. Vamos utilizar da herança em nossos objetos do tipo CondimentDecorator. O motivo de se usar herança na classe Decorator é  pelo simples fato de se ter o mesmo tipo dos objetos que vão ser decorados. O uso de herança é justamente para atingir  essa correspondência de tipo.

1
2
3
4
5
package br.eti.albertoleal.decorator;
 
public abstract class CondimentDecorator extends Pizza {
 
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package br.eti.albertoleal.decorator;
 
public class Oregano extends CondimentDecorator {
	Pizza pizza;
 
	public Oregano(Pizza pz) {
		pizza = pz;
	}
 
	@Override
	public String getDescription() {
		return pizza.getDescription() + ", Oregano";
	}
 
	@Override
	public double cost() {
		return .50 + pizza.cost();
	}
 
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package br.eti.albertoleal.decorator;
 
public class Tomato extends CondimentDecorator {
	Pizza pizza;
 
	public Tomato(Pizza pz){
		pizza = pz;
	}
 
	@Override
	public String getDescription() {
		return pizza.getDescription() + ", Tomato ";
	}
 
	@Override
	public double cost() {
		return .10 + pizza.cost();
	}
 
}

Se você estava atento reparou que a cada condimento que é adicionado na pizza um valor correspondente ao condimento é somado ao valor da pizza. Essa é a idéia do decorator. Estou decorando um objeto pizza com diversos outros componentes. Um outro exemplo, bastante comum de se encontrar pela internet, são as janelas gráficas. O ato de decorar uma janela gráfica com diversos componentes de apresentação, tais como: barra de rolagem, campos de texto e por aí vai.

Chegou a hora de testarmos o nosso código, criar uma pizza e adicionar alguns condimentos a ela e constatar se a nossa “decoração” funciona:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package br.eti.albertoleal.decorator;
 
public class Pizzaiolo {
 
	public static void main(String[] args) {
 
		Pizza pz = new Cheese();
 
		pz = new Tomato(pz);
		pz = new Tomato(pz);
		pz = new Oregano(pz);
		pz = new Tomato(pz);
		pz = new Oregano(pz);
		pz = new Tomato(pz);
 
		System.out.println(pz.getDescription());		
 
	}
 
}

Concluindo:

  • A herança é uma maneira de estender comportamentos, mas não é a melhor maneira de obter flexibilidade;
  • Composição e delegação são boas maneiras de se adicionar funcionalidades em tempo de execução;
  • A utilização de um componente decorator é simplesmente decorar um objeto, e o objeto decorado não precisa conhecer os decoradores;
  • É muito importante que os objetos decoradores sejam espelhos do objeto que vão decorar, justamente para ter uma correspondência de tipo.

Git: Quem fez merda no meu código?

Posted by Alberto Leal on June 19th, 2009

Cenário: Você está em uma reunião participando de um code review, quando algum desenvolvedor vira e fala: “Quem comentou a linha 12? Eu fiz esse código e aquele fragmento era importante!”. Pergunta: O culpado aparece rápido? Pode ser que sim. Mas, caso não apareça  ninguém para assumir a culpa, utilize o comando ‘git blame’ para descobrir quem fez cada modificação.

Exemplo:

$ git blame workspace/ProjectXPTO/WebContent/file.jsp -L 10,18
73e51f4f (Desenvolvedor A 2009-03-10 09:07:53 -0400 10)
73e51f4f (Desenvolvedor A 2009-03-10 09:07:53 -0400 11)  <script>
73e51f4f (Desenvolvedor A 2009-03-10 09:07:53 -0400 12)         // var windowName;
7ue8d049 (Desenvolvedor B 2009-06-18 16:42:48 -0400 13)
7ue8d049 (Desenvolvedor B 2009-06-18 16:42:48 -0400 14) function cleanUpVariable(variable){
7ue8d049 (Desenvolvedor B 2009-06-18 16:42:48 -0400 15)  var = j;
7ue8d049 (Desenvolvedor B 2009-06-18 16:42:48 -0400 16)  j = variable.replace(/[^0-9A-Za-z]+/g, "");
7ue8d049 (Desenvolvedor B 2009-06-18 16:42:48 -0400 17)  return j;
7ue8d049 (Desenvolvedor B 2009-06-18 16:42:48 -0400 18) }

Se você não passar o parâmetro -L serão exibidas todas as linhas do seu arquivo.  No caso acima deu para perceber que o responsável por comentar a variável “windowName” foi o “Desenvolvedor A”.

Agora você já sabe como descobrir quem faz cada besteira nos seus arquivos.

Git requer estudo, sim

Posted by Alberto Leal on June 19th, 2009

Acredito que o título desse post diz muito por si só. Mas, vou tentar expandí-lo um pouco mais. Só para constar, fui impulsionado a escrever esse post devido a algumas mensagens que acompanhei pelo twitter.

Existem diversos controladores de versão no mercado, tais como: Harvest, CVS, SVN, Clear Quest e por aí vai. Porém, o Git possui uma idéia, filosofia diferente destes que acabei de citar. Git é um SCM distribuído. Não vou entrar em detalhes sobre as diferenças agora, vamos deixar para uma outra ocasião.

A mensagem que quero passar é a seguinte:
Git é difícil?  Não.
Uso SVN/CVS na minha empresa há muitos anos, posso mudar tudo de uma vez para o GIT - já que Git não é difícil? Não aconselho.

Usar um controlador de versão não envolve apenas adicionar arquivos e comitá-los. Existem diversas tarefas que, às vezes, temos que fazer, como por exemplo: Quebrando um commit e cancelando algumas alterações. Pode ser que você já saiba fazê-lo no outro SCM que você vem utilizando, mas ainda não sabe fazê-lo no Git.

Se você, simplesmente, mudar de SCM de uma hora para a outra fatalmente terá problemas e terá que recorrer ao grande amigo Google. Alguns problemas triviais não lhe tomará muito tempo, por outro lado, outros não serão tão triviais quanto possam parecer e tomarão mais tempo do que você gostaria.

Minha sugestão é a seguinte, comece utilizando Git em um projeto antes de migrar todos os outros. Desse jeito você perceberá como o Git trabalha e como tirar o maior proveito dele. Além de se deparar com os mais diversos tipos de problemas.

Até a próxima!


Copyright © 2007 Alberto Leal. All rights reserved.