sexta-feira, 22 de outubro de 2010

PhpDescribe agora com mais documentação.

O PhpDescribe, ferramenta para escrever especificações ativas de software em uma filosofia semelhante ao do BDD, lançou seu novo site com informações a respeito da ferramenta de teste de software.

É uma ferramenta muito promissora para quem quer unir a escrita de especificação com a escrita dos testes de software. Além disso é um exemplo de código usando novas funcionalidades do php 5.3.

quarta-feira, 22 de setembro de 2010

Trees, forests and applications... please let´s turn tests in real specifications.

To understand the tree, you need to look at the forest. To understand a forest you need to look at the trees. Clients normaly want to see the forest, but developers like to develop trees. A big step taken by the agile process is to start moving the developers to see the forest, not only the trees that compose that forest.

When I was trying to learn how to draw, the good teachers kept telling me to do things from the outer to the inner. TDD and BDD brought a broader vision to this. But I still have a feeling that we need to start from a little bit before and we also need to have a beeter picture of the tree.

The standart bdd tools, using a strict grammar is nice. But, how do we see the results? Are they results at all?

No, they are the specifications. For tests we have results and for specification we have what? I think in examples and these can be working or not workin. So, how do I take a good look at the specifications and see what parts are working, incomplete, not working....

I have not seen yet this being addressed by any tool. Colored test results from a little piece of specification, as most tools will produce, won´t give me the forest view. Forest have leaves, flowers, stems and other important things to be noticed to understand the forest. I think we should think more in writing specs to be read and understood by humans than by continuous integration tools. They should be extremely easy to navigate, search and write. Images are essential in some place, they need to have a way to be added.

So I think there is a gap to be filled.... that´s why I´ve started PSpec.

terça-feira, 20 de julho de 2010

A simple symfony application deploy using shell script.

This is something that can be used to deploy an app to an staging environment. After that you can sync it somehow, but I prefer to export again to prod to keep the fidelity from the release launched with the repo release.

It´s nice to see how many things can be done with shell scritp without the need to configure those weird xmls (IMO, of course). It´s just more.... simple.

#!/bin/bash
die () {
echo >&2 "$@"
exit 1
}

// validate the parameters count....

[ "$#" -eq 1 ] || die "Voce precisa informar o nome da release para ser o nome do diretorio gerado dentro de prod_online"

// exports the code from a local repo. (if you need from a foreign with ssh, ask that I can publish some info also)

svn export --force file:///data/svn/reuni-on/trunk /data/web/reuni/prod_online/$1

// override the config file with one specific to prod environment.

cp /data/web/reuni/deploy_script/testesSincronia.conf.tmp /data/web/reuni/prod_online/$1/web/testesSincronia/conf.php

// create dirs that are not so good to be on the repo.

mkdir /data/web/reuni/prod_online/$1/cache
mkdir /data/web/reuni/prod_online/$1/log
mkdir /data/web/reuni/prod_online/$1/data/offlineParaDownload

//allow to write into this dirs ( here you will probably want a more restrictive permission)
chmod 777 -R /data/web/reuni/prod_online/$1/cache
chmod 777 -R /data/web/reuni/prod_online/$1/log
chmod 777 -R /data/web/reuni/prod_online/$1/data/offlineParaDownload

// clear symfony cache
php /data/web/reuni/prod_online/$1/symfony cc

quarta-feira, 14 de julho de 2010

Robots.txt url without trailing slashes. - ALERT -

To leave a url in the robots.txt without a trailing slash can steal your sleep sometime. This makes the seach engine think you are blocking any match that starts with that url and it can disallow or allow unwanted urls, read these to understand better:

http://www.google.com/support/webmasters/bin/answer.py?hl=br&answer=156449

http://www.webmasterworld.com/forum93/892.htm

quinta-feira, 1 de julho de 2010

Imagens e outros downloads com acesso restrito em PHP... como mostrar?

Quem sempre mostrou imagens usando simplesmente a URL da mesma em um tag img, quando precisa restringir o acesso para elas, muitas vezes fica confuso em como fazer isso. A receita é bem simples:

1 - coloque a imagem fora do diretório que é servido pelo apache.

2 - crie um script que faz o controle de acesso

3 - se o usuário estiver autorizado, então devemos ler a imagem e mandar direto pro usuário, para isso podemos usar o método fpassthru() que já vai jogando a imagem direto pro buffer de saída, gerando um ganho de performance.

4 - depois disso é só fazer uma referência para aquele script, algo como < src="'mostraImagem.php?id="444'">

simples né? olhaí um exemplo de como fazer isso:


$targetPath = $caminhoDaMinhaImagem . '.jpg'; // presumindo que tem esta extensão, é claro.
$fp = fopen($targetPath, 'rb'); // abre para ler um binário
header("Content-Type: image/jpg"); // manda um header dizendo que é um jpg
header("Content-Length: " . filesize($targetPath)); // da a dica do tamanho da img pro browser
fpassthru($fp); // manda
// se você tiver dentro de algum framework, você tem que dar um jeito de não mandar mais nada, um método "bruto", mas prático, é simplesmente die();


Dê uma olhada melhor na documentação dessa função, la tem alguns exemplos muito úteis:

http://php.net/manual/en/function.fpassthru.php

quarta-feira, 30 de junho de 2010

Doctrine - Operações em lote ou "batch updates" - algums dicas

O Doctrine não é uma ferramenta feita para operações em lote, ele é um ORM. Mas tem alguns momentos que já temos o método na nossa camada de negócio e queremos chama-lo um monte de vezes para executar alguma manutenção no banco de dados ou algo assim.

Nestes momentos nem sempre é necessário reescrever tudo em um sql otimizado, em casos mais simples ou não tão críticos, podemos usar o que já temos. Porém, fazer esse tipo de operação no Doctrine requer alguns cuidados que temos aprendido com o tempo. Coloco aqui algumas dicas para quem quiser pular a fase do aprendizado pelo erro. Mais abaixo também coloco um exemplo de código para o tão famigerado e entretanto tão usado copy and paste.

Dicas:

1 - Faça um looping iniciando e "commitando" a transação. Isso aumenta em muito a velocidade de insert/update no banco. A quantidade de registros atualizados a cada iteração vai ter que ser definida na tentativa e erro, mas quanto mais simples a operação, maior a quantidade de itens que podem ser incluidos. Vale perceber que mesmo que a transação funcione, se forem muitos itens, o resultado final pode ficar mais lento mesmo assim.

2 - Sempre chame o método free() passando o parâmetro true para seus objetos instanciados pelo doctrine para que ele libere a memória usada por aquele objeto. Eu chamo também um unset() logo em seguida.

3 - Se você usar uma action no symfony (isso é, se é que você usa o symfony), ele tem uma mania de querer repetir a operação depois que termina. Por algum motivo que ainda não descobri, ele faz um redirect ou forward para a mesma action, então eu coloco aquele die() no final. Sei que ideal seria uma task rodando do shell, mas faço assim pq acho mais simples, principalmente para operações que vão rodar uma vez só. Se for algo que vai ser ativado pelo cron, aí não tem como fugir das tasks.

Para recortar e colar (divirta-se):


function executeRecalculateAllRatings() {
set_time_limit(3600);
$min = 0;
$increment = 1000;
$last = 50000;
$count = 0;
while ($min <= $last) { echo "<>NEW TRANSACTION - $min <>";
Doctrine_Manager::connection()->beginTransaction();
$comments = CommentTable::build()->findByIdRange($min, $min + $increment);
foreach($comments as $comment) {
$res = RatingLogTable::build()->calculateCommentRatingTotal($comment['id']);
$comment->setRating($res[0],$res[1]);
$comment->save();
$comment->free(true);
unset($comment);
echo $count++ . ' - ';
}
$min = $min + $increment;
Doctrine_Manager::connection()->commit();
}
die();
}

quarta-feira, 23 de junho de 2010

Git Submodules - um recurso para gerenciar dependências no lugar de svn externals.

Submodules & GIT - usando bibliotecas externas.

Quem está acostumado em gerenciar suas bibliotecas em svn usando o recurso externals, quando considera usar o GIT, geralmente tem dúvida a respeito de como trabalhar. Já escrevi aqui um artivo a respeito de svn externals e agora que estou migrando pro git então escrevo este aqui também para quem quiser me acompanhar.

Dois recursos normalmente surgem quando pesquisamos a respeito do assunto:
  • submodules
  • subtree merge strategy
Vamos tratar aqui do primeiro, porém quem quiser pesquisar o segundo, veja a comparação entre submodules e subtree merge strategy na documentação.

O que são submodules?

Na documentação diz que submodules ou submódulos permitem repositórios externos serem adicionados dentro de um subdiretório dedicado da arvore do nosso projeto, sempre apontando para um commit específico.

Bom... uma parte de cada vez:

repositórios externos
são outros repositórios em git.

diretórios dedicado
o diretório onde o submódulo fica tem sua arvore específica, inclusive a pasta .git com suas próprias configurações. Não pode ser feito merge com a arvore do repositório pai.

commit específico
quando adicionamos um submódulo a uma arvore, estamos adicionando um commit específico. Isso quer dizer que atrelamos ele a uma versão (um SHA). Toda vez que alguém baixar este projeto e pedir o submódulo ele vai receber esta versão mesmo que o repositório original esteja bem mais adiantado.

Isso é legal. Quero um pra mim. Como eu faço para criar um submódulo?

você deve usar um comando semelhante à este aqui (nessa hora o melhor mesmo é consultar o manual do git):

git submodule add [URL do repositório] [pasta de destino]
git submodule add http://github.com/brunoreis/pspec.git extlibs/pspec


com isso ele vai criar um repositório para o pspec na pasta extlibs/pspec. Vale a pena dar uma olhada nesta pasta, dentro do diretório .git, e ver o que tem nos arquivos texto de configuração. Com certeza vai auxiliar a encaixar as peças do quebra-cabeças. Ah, e também olhe o .git da raiz do seu projeto.

Bom, então é só isso? Meu submódulo está criado, posso mandar meu projeto para o github e ficar famoso porque uso submódulos e o pspec para especificar e testar meu software?

Muita hora nessa calma! Ainda temos algumas coisas a fazer antes. Ao criar o submodule, como já dissemos antes, atrelamos ele a um SHA específico. Os arquivos do repositório, a princípio, não ficam dentro do nosso repositório, mas o SHA sim. Temos então que adicionar o subdiretório criado à arvore original para que ele possa ser integrado ao nosso repositório.

Fazemos assim:
git add extlibs/pspec
git commig -m "agora sim com pspec"

Agora está lá... e se quiser subir para o repo de origem, não esqueça de fazer um push.

Isso quer dizer que quem fizer checkout no meu projeto já vai baixar o submódulo?

Não. Como já falei antes, você mandou apenas o SHA. Assim quando você fizer checkout vai trazer apenas uma referência à aquele submodulo, sem baixar o conteúdo do mesmo. Então após fazer checkout do seu repo, você ainda vai ter que fazer o seguinte:
git submodules init
git submodules update

Com isso ele vai trazer o conteúdo do(s) submódulos de acordo com o SHA de cada um.

E como eu faço pra saber se um projeto que baixei tem submódulos?

essa é fácil, é só rodar
git submodules

ele mostra os submódulos e também o SHA de cada um.

Beleza, mas agora eu sei que tem algo novo que eu preciso em um submódulo, como eu atualizo ele?

Simples, como o submódulo tem lá sua arvore e seu .git, etc.. porém este repositório está atrelado a um commit (sha) específico. Então precisamos fazer um checkout do branch que você quer, ex:

git checkout master

depois disso você pode usar

git pull

para atualizar.

Ah, e lembre-se de que depois que você fez isso, você tem que adicionar novamente o submodule ao repositório e fazer um commit (da atualização do SHA) para que os outros possam ter essa atualização.

Ao fazer essa atualização não coloque uma barra depois do nome do submodule. Se você fizer isso vai bagunçar tudo. Ou seja, use:
submodule add extlibs/pspec


mas NÃO USE

submodule add extlibs/pspec/ <--------------- Essa barra faz @#$@%@!!


Ta bom, ta bom....Hum.... e....

Se eu quiser atualizar todos de uma vez?

É só fazer assim:

git submodule foreach "git pull"

Esse comando eu achei muito interessante. Ele roda por todos os submódulos e executa o comando que for passado para ele, no noso caso o pull. Não esqueça de mandar esta alteração adicionando os submodules novamente à arvore principal.

Beleza, mas agora que estou no meu projeto, vi que tem um bug no repositório do submódulo. Tem como eu arrumar isso sem fazer checkout do sub em outro diretório?

Sim. Você pode entrar no dir do submódulo, fazer um checkout, alterar, fazer um commit e mandar novamente para o repo original.

Se você fizer isso e encontrar um erro dizendo que o original não aceita commits deste, leia este post a respeito do uso de "bare repositories".

Ta Bom.

Espero que você tenha sucesso usando os submódulos. Eles me parecem bem mais simples e dinâmicos que os externals do svn. Ainda estou aprendendo o git, então deve ter algo aqui que pode ser feito de uma maneira melhor ou então algo que você não entendeu. Peço que você acrescente seu comentário que se eu puder, respondo. Assim agregamos mais informações para os próximos não terem que ficar pesquisando as mesmas coisas que nós.

Sucesso!

--------------
Ah...

Algumas referências citadas e usadas aqui:

http://www.kernel.org/pub/software/scm/git/docs/git-submodule.html

http://book.git-scm.com/5_submodules.html

https://git.wiki.kernel.org/index.php/GitSubmoduleTutorial

http://stackoverflow.com/questions/804545/what-is-this-git-warning-message-when-pushing-changes-to-a-remote-repository