Link: Vamos todos impedir a regulamentação da profissão de analista de sistema

17 04 2008

Poderia escrever longo texto explicando porque não é uma boa coisa a regulamentação, mas já fizeram isso muito bem em diversos blogs, foruns, listas de discussão, etc etc etc…

Que tal essa sugestão para demonstrar seu descontentamento com isso ?





off: Locaweb sux

30 03 2008

Não tenho postado muita coisa aqui (apesar de ter o que postar) principalmente por falta de tempo.

De forma resumida, ultimas duas semanas, problemas na locaweb em 14 dias…

Problemas pra resolver nomes, lentidao, servidor web fora, e nesse momento servidor mysql fora. Só espero que não tenham sumido com meu banco, últimos 4 backups remotos não foram bem sucedidos…

locaweb

E um viva para locaweb…

Update:
Segundo o internetsupervision





uhmmmm: php2java

4 03 2008

Segue o link
http://www.numiton.com





Linq for php

25 01 2008




Dica rápida: printf(”{0} {1} {0} “, ‘foo’, ‘bar’);

14 12 2007

Ok, não é bem isso, mas é quase. Segue a conversa:

<anmsx> printf("ola {0}, hoje é {1}. Ja disse seu nome, {0} ? ", ‘anmsx’, ‘domingo’);
<anmsx> queria algo assim no php
<anmsx> tipo q tem no c#
<ecl> ahhaha
<anmsx> sacou a ideia ?
<ecl> sim
<anmsx> da pra fazer em codigo mesmo
<ecl> mas da pra fazer isso atualmente com o recurso atual tambem, ta ligado?
<anmsx> si
<ecl> hahah, falei cheio de redundancia
<anmsx> func_get_args ou coisa assim, nao ?
<ecl> anmsx: falo no printf mesmo
<anmsx> ah é ?
<anmsx> como ?
<anmsx> isso eu nao sei
<ecl> %[numero do arg]$[tipo]
<anmsx> 5.3 ?
<ecl> nao
<ecl> antigo.
<anmsx> xover
<ecl> de qualquer forma, usando o {N} para string, seria legal
<anmsx> certeza q é dessa forma q colocou ?
<anmsx> onde tem isso na doc ?
<anmsx> nao funcionou
<anmsx> $ php -r ‘echo printf("Ola %1\$s hoje é %2\$s, certo %1\$s ?", "anmsx", "domingo");’
<anmsx> Ola anmsx hoje é domingo, certo anmsx ?
<anmsx> cool





Link: Dezenas de slides

22 11 2007




Rapidinha: Obter cotação da bolsa de valores em tempo real …

19 11 2007

… claro, com um pequeno atraso de 15 minutos. E ajuda do sempre útil simplexml, do PHP5. Segue:

<?php
// author: Eziel Silva
@list($self, $papel, $time, $tot) = $argv;
if (!$papel) {
    echo sprintf('uso:    %s <PAPEL> [temp][valor]%s', $self, "\n");
    echo sprintf('PAPEL:  VALE5%s', "\n");
    echo sprintf('temp:   tempo de atualizacao - default = 20%s', "\n");
    echo sprintf('valor:  quanto em papeis da empresa voce possui%s', "\n");
    return 1;
}

$url  = sprintf('http://www.bovespa.com.br/Cotacoes2000/formCotacoesMobile.asp?codsocemi=%s', $papel);
$sXml = @simplexml_load_string(@file_get_contents($url));

if (!$sXml) {
    echo sprintf('Simbolo "%s" nao encontrado', $papel);
    return 1;
}

$format = "Hor: %s Osc.: %s%% Rend.: %s\n";
if (!$tot) {
    $format = "Hor: %s Osc.: %s%%\n";
}
if (!$time) {
    $time = 20;
}

while(true) {
    $sXml = @simplexml_load_string(@file_get_contents($url));
    if (!$sXml) {
        echo sprintf('Erro atualizando... aguardando 5s%s',"\n");
        sleep(5);
        continue;
    }
    $c = $tot * str_replace(',','.', $sXml->PAPEL['OSCILACAO']) / 100;
    // hack pra me deixar feliz... caso esteja perdendo $$$, 
    // descomente a linha abaixo
    //$c = $c * -1; 
    echo sprintf($format, $sXml->PAPEL['HORA'], $sXml->PAPEL['OSCILACAO'], $c);
    sleep($time);
}

$ php bov.php
uso: bov.php [temp][valor]
PAPEL: VALE5
temp: tempo de atualizacao – default = 20
valor: quanto em papeis da empresa voce possui

$ php bov.php VALE5
Hor: 18:08:06 Osc.: -3,55%

$ php bov.php VALE5 5 1000
Hor: 18:08:06 Osc.: -3,55% Rend.: -35.5

Arquivo:
bov.php





PHP / CruiseControl

19 11 2007




PHP + TDD + “Generics”

16 11 2007

(Observação: Poucas coisas são tão terríveis quanto se formatar um post nesse wordpress. Todos devem ficar assim…)

“Test-Driven Development (TDD) is a software development technique consisting of short iterations where new test cases covering the desired improvement or new functionality are written first, then the production code necessary to pass the tests is implemented, and finally the software is refactored to accommodate changes. The availability of tests before actual development ensures rapid feedback after any change. Practitioners emphasize that test-driven development is a method of designing software, not merely a method of testing.”

Acredito que já conheçam TDD. O que ??? Não conhece ??? Ok, ótima hora para conhecer:

Wikipedia – TDD
Introduction to Test Driven Design (TDD)
testdriven.com
improveit – tdd
phpunit

Não será eu quem vai dizer os benefícios de se utilizar TDD, até porque não é o objetivo deste post. Vamos ver de forma bem rápida como podemos criar uma classe que tem o comportamente semelhante a generics em java. E, novamente, não será eu que vai dizer o que são generics.

1 – Os testes
Vejamos um simples teste, com os comentários:

TestGenericList.php

<?php

include 'g.class.php';
include 'invalidgenerictypeexception.class.php';
include 'genericlist.class.php';

// Classe que servira de modelo e teste para o que
// vamos desenvolver
class TestGenericList extends PHPUnit_Framework_TestCase {

    /**
    * Testa o tamanho da nossa lista
    */
    public function testSize()
    {
        // instanciamos a GenericList
        // o parametro que vamos passar indica
        // o tipo de lista que teremos, neste
        // caso uma lista de Integer (int)
        // List l = new List<Integer>()
        $list = new GenericList(G::Integer);
        $list->add(1); // adicionamos um item...
        $list->add(2); // ... e mais um ...
        $list->add(3); // ... e mais um, totalizando tres
        
        // testamos se o tamanho da nossa lista
        // realmente eh igual a 3
        $this->assertEquals($list->size(), 3);
    }

    /*
        Note que ao final do teste acima, ja temos pelo menos
        tres metodos e duas propriedades definidas:
        __construct($param):
            O construtor da classe, vai receber pelo menos um
            parametro, indicando o tipo de lista. $param
            devera ser salvo para uso futuro, entao teremos
            uma propriedade na classe para isso
        add($param):
            Adiciona um item na lista. Assim como o parametro
            passado no construtor, deveremos salvar este parametro
            para uso futuro. Entao teremos mais uma propriedade na 
            classe
        size():
            Retorna o tamanho da lista. Provavelmente vai retornar
            a quantidade de itens adicionados em add($param), que
            estao armazenados em uma propriedade da classe, que
            certamente sera um array. Pensando em sizeof() ?
    */

    /**
    * Testa uma lista de Integers se aceita adicao
    * de somente novos integers
    */
    public function testAddSameTypeInteger()
    {
        // criamos uma lista de integers
        $list = new GenericList(G::Integer);
        // adicionamos um integer
        $list->add(1);
        // se tudo deu certo, teremos um integer
        // na lista e ela vai ter um tamanho = 1
        $this->assertEquals($list->size(), 1);
    }
    
    /**
    * Testa uma lista de Strings se aceita adicao
    * de somente novas Strings
    */
    public function testAddSameTypeString()
    {
        // criamos uma lista de Strings
        $list = new GenericList(G::String);
        // adicionamos uma string
        $list->add('foo');
        // se tudo deu certo, teremos uma string
        // na lista e ela vai ter um tamanho = 1
        $this->assertEquals($list->size(), 1);
    }

    /**
    * Testa uma lista de Doubles se aceita adicao
    * de somente novas Doubles
    */
    public function testAddSameTypeDouble()
    {
        // criamos uma lista de doubles
        $list = new GenericList(G::Double);
        // adicionamos um double
        $list->add(10.1);
        // e se tudo deu certo, teremos um double
        // na lista e ela vai ter um tamanho = 1
        $this->assertEquals($list->size(), 1);
    }
    
    /**
    * Testa uma lista de Objetos se aceita adicao
    * de somente novas Objetos DO MESMO TIPO. Ou seja
    * Uma lista de "new Pessoa()" deve aceitar adicao
    * de somente "new Pessoa()"
    */
    public function testAddSameTypeObject()
    {
        // criamos um objeto que servira de
        // modelo para a lista...
        $obj = new StdClass();
        
        // ...e um objeto que sera adiciona na lista.
        // Note que ambos sao instancias de StdClass
        $obj2 = new StdClass();
        
        // criamos uma lista de objetos do tipo
        // stdclass
        $list = new GenericList($obj);
        // e adicionamos um objeto a esta lista
        $list->add($obj2);
        // se tudo deu certo, teremos um objeto
        // na lista e ela vai ter um tamanho = 1
        $this->assertEquals($list->size(), 1);

        // novamente criamos uma lista de objetos do tipo
        // stdclass, mas desta vez ao inves de passar um objeto
        // da classe, passamos o tipo de objeto que a lista
        // ira conter
        $list = new GenericList(G::type('stdclass')); // same as above, but using class name
        // e adicionamos um objeto do tipo especificado a lista
        $list->add($obj2);
        // novamente, se tudo deu certo, teremos uma
        // lista de tamanho = 1, e testamos isso
        $this->assertEquals($list->size(), 1);
    }
    
    /**
    * Aqui iremos forcar um erro no teste
    * Vamos criar uma lista de Integer e tentar
    * adicionar outros tipos. Em todos os casos
    * diferentes do tipo original, devera ocorrer
    * um erro
    */
    public function testAddDifferentTypeInteger()
    {
        // criamos a lista de integer
        $list = new GenericList(G::Integer);

        // nos casos em que vamos utilizar algo diferente
        // de integer, utilizamos bloco try/catch. O
        // comportamento da lista sera de gerar uma
        // exception no caso de adicao de um tipo diferente

        try {
            // tentamos adicionar uma string na lista de
            // integer
            $list->add('foo');
            
            // nao deveria chegar neste ponto, visto que
            // na linha acima deveria ter sido gerada. Entao
            // dizemos ao phpunit que este teste falhou
            $this->fail('Generic Integer accepted a string');
        } catch (InvalidGenericTypeException $e) {}

        try {
            $list->add(2.1);
            $this->fail('Generic Integer accepted a double');
        } catch (InvalidGenericTypeException $e) {}

        try {
            $list->add(new StdClass());
            $this->fail('Generic Integer accepted a object');
        } catch (InvalidGenericTypeException $e) {}
    }
    
    /**
    * Aqui iremos forcar um erro no teste
    * Vamos criar uma lista de Strings e tentar
    * adicionar outros tipos. Em todos os casos
    * diferentes do tipo original, devera ocorrer
    * um erro
    */
    public function testAddDifferentTypeString()
    {
        // criamos a lista de strings
        $list = new GenericList(G::String);

        // e tentamos adicionar outros tipos, do mesmo
        // modo que fazemos no teste anterior
        
        try {
            $list->add(1);
            $this->fail('Generic String accepted a integer');
        } catch (InvalidGenericTypeException $e) {}

        try {
            $list->add(1.0);
            $this->fail('Generic String accepted a double');
        } catch (InvalidGenericTypeException $e) {}

        try {
            $list->add(new StdClass());
            $this->fail('Generic String accepted a object');
        } catch (InvalidGenericTypeException $e) {}
    }
    
    /**
    * Aqui tambem iremos forcar um erro no teste
    * Vamos criar uma lista de Double e tentar
    * adicionar outros tipos. Em todos os casos
    * diferentes do tipo original, devera ocorrer
    * um erro
    */
    public function testAddDifferentTypeDouble()
    {
        // criamos a lista de Double
        $list = new GenericList(G::Double);

        // e depois eh aquilo...

        try {
            $list->add(1);
            $this->fail('Generic Double accepted a integer');
        } catch (InvalidGenericTypeException $e) {}

        try {
            $list->add('foo');
            $this->fail('Generic Double accepted a string');
        } catch (InvalidGenericTypeException $e) {}

        try {
            $list->add(new StdClass());
            $this->fail('Generic Double accepted a object');
        } catch (InvalidGenericTypeException $e) {}
    }
    
    /**
    * Novamente o erro.
    * Vamos criar uma lista de Objetos e tentar
    * adicionar outros tipos. Em todos os casos
    * diferentes do tipo original, devera ocorrer
    * um erro
    */
    public function testAddDifferentTypeObject()
    {
        $obj = new StdClass();
        // criamos uma lista de objetos StdClass
        $list = new GenericList($obj);

        try {
            // nao podemos adicionar Integer
            $list->add(1);
            $this->fail('Generic Object accepted a integer');
        } catch (InvalidGenericTypeException $e) {}

        try {
            // e nem String
            $list->add('foo');
            $this->fail('Generic Object accepted a string');
        } catch (InvalidGenericTypeException $e) {}

        try {
            // nem double
            $list->add(2.5);
            $this->fail('Generic Object accepted a double');
        } catch (InvalidGenericTypeException $e) {}

        try {
            // e nem outro tipo de objeto, neste caso uma
            // Exception
            $list->add( new Exception());
            $this->fail('Generic Object accepted a Exception');
        } catch (InvalidGenericTypeException $e) {}

        // mesma ideia, mas utilizando uma lista criada
        // com o nome da classe
        $obj = new StdClass();
        $list = new GenericList(G::type('stdclass'));

        try {
            $list->add(1);
            $this->fail('Generic Object accepted a integer');
        } catch (InvalidGenericTypeException $e) {}

    }
    
    /**
    * Neste teste vamos verificar se a nossa lista
    * aceita um objeto de uma classe diferente da
    * classe definida como o tipo da lista, mas sendo
    * uma classe "extendida":
    *
    * class Car{}
    * class Ferrari extends Car {}
    *
    * criamos uma lista de Car e tentaremos adicionar
    * uma Ferrari
    */
    public function testAddParentClassObject()
    {
        // criamos 2 classes em runtime
        // php nao aceita criacao de nested classes
        eval('class Car {}');
        eval('class Ferrari extends Car {}');
        
        $obj = new Car();
        // criamos uma lista de Car, da mesma forma que criavamos
        // anteriormente. Entao se tentarmos adicionar uma Ferrari
        // na lista, devera ser gerada uma exception
        $list = new GenericList($obj); // creates a Car's list

        try {
            // adicionar uma Ferrari em uma lista de Car
            // deve gerar uma exception
            $list->add(new Ferrari()); // must throw a exception
            $this->fail('Generic Object accepted a parent class object without G::extend');
        } catch (InvalidGenericTypeException $e) { }

        $obj = new Car();

        // agora vamos definir que a nossa lista pode
        // receber alem de Car, classes que herdem Car
        // Collection c = new Collection<? extends Car>()
        $list = new GenericList(G::extend($obj));
        // Ferrari herda Car, entao esperamos que funcione
        $list->add(new Ferrari()); 

        // fazemos a mesma coisa, mas utilizando o nome da classe
        // ao inves de um objeto
        
        $obj = new Car();
        $list = new GenericList(G::type('car')); // creates a Car's list

        try {
            $list->add(new Ferrari()); // must throw a exception
            $this->fail('Generic Object accepted a parent class object without G::extend');
        } catch (InvalidGenericTypeException $e) { }

        $obj = new Car();
        $list = new GenericList(G::extend($obj));
        $list->add(new Ferrari()); // should work
    }
}

Após terminarmos de escrever o teste, temos bem definido uma grande parte da classe que vamos implementar. Já temos pelo menos 3 métodos públicos definidos:

__construct($param):
O construtor da classe, vai receber pelo menos um
parâmetro, indicando o tipo de lista. $param
deverá ser salvo para uso futuro, então teremos
uma propriedade na classe para isso

add($param):
Adiciona um item na lista. Assim como o parâmetro
passado no construtor, deveremos salvar este parâmetro
para uso futuro. Então teremos mais uma propriedade na
classe

size():
Retorna o tamanho da lista. Provavelmente vai retornar
a quantidade de itens adicionados em add($param), que
estao armazenados em uma propriedade da classe, que
certamente sera um array. Pensando em sizeof() ?

E também pelo menos 2 propriedades.
Observando o teste notamos também mais duas classes: G, que contem os tipos disponíveis e dois métodos, e também uma classe InvalidGenericTypeException, que representa as exceptions geradas por GenericList.

2 – Implementação: g.class.php
A Classe G (de Generic), contém tres constantes – Integer, String e Double – e dois métodos estáticos – extend e type.
O método type será utilizado para informar para lista o tipo de valor que ela vai conter, sem que ela precise descobrir por si. Já o método extend será utilizado para informar a lista que o tipo a ser utilizado pode ser também subtipos. Os dois métodos vão retornar um array que será trabalhado pela lista. Vamos a implementação:

g.class.php

<?php
/**
* Classe que contem a definicao dos tipos disponiveis
*/
class G {
    /**
    * Constantes com os tipos
    */
    const Integer = 'integer';
    const String  = 'string';
    const Double  = 'double';

    public static function extend($obj)
    {
        if (!is_object($obj)) {
            throw new InvalidGenericTypeException('G::parentsOf must be called with a valid object');
        }
        return array('extend' => strtolower(get_class($obj)));
    }
    
    public static function type($val)
    {
        return array('type' => strtolower($val));
    }
}

2 – Implementação: invalidgenerictypeexception.class.php
Uma exception simples, desnecessária explicação

invalidgenerictypeexception.class.php

<?php
class InvalidGenericTypeException extends Exception {
    public function __construct($message)
    {
        parent::__construct($message);
    }
}

4 – Implementação: genericlist.class.php
Aqui temos, finalmente, a implementação da lista em si. Note que esta implementação chega a ser bem mais simples que o teste. Veja o código e acompanhe pelos comentários:

genericlist.class.php

<?php
/**
* Implementacao da lista
*
* Tem apenas proposito educacional, poderia implementar
* algum iterator, ter metodos para remover ou retornar
* um item, buscar por um item, etc.
*/
class GenericList {
    
    /**
    * Tipo de valores da lista
    */
    private $type = null;
    
    /**
    * Valores da lista
    */
    private $values = array();
    
    /**
    * Informa se o tipo deve levar em consideracao
    * tambem os subtipos
    */
    private $useExtend = false;
    
    /**
    * Construtor da classe
    *
    * Baseado no parametro recebido, inicializa as propriedades
    * $this->type e $this->useExtend
    */
    public function __construct($type)
    {
        // se o parametro for um objeto, o tipo
        // da lista sera definido para o nome da
        // classe utilizada para criacao do objeto,
        // em minusculo
        if (is_object($type)) {
            $this->type = strtolower(get_class($type));
        } 
        // se nao for um objeto, pode ser um array,
        // G::String, G::Double ou G::Integer
        else {
            // caso seja um array...
            if (is_array($type)) {
                // ... verifica se existe a chave
                // extend. Caso exista, significa que
                // o tipo foi definido por meio de
                // G::extend
                if (array_key_exists('extend', $type)) {
                    // define que estara levando em consideracao
                    // os subtipos do tipo
                    $this->useExtend = true;
                    // define o tipo
                    $this->type = $type['extend'];
                // caso exista a chave 'type', significa que o tipo
                // da lista foi definida com g::type. Apenas
                // pega o valor de type e seta como padrao para
                // a lista
                } else if(array_key_exists('type', $type)) {
                    $this->type = $type['type'];
                }
                // nao deveria chegar aqui
                else {
                    throw new InvalidGenericTypeException('Undefined type');
                }
            }
            // se nao for array, o tipo foi passado diretamente como
            // parametro. Apenas utiliza-o
            else {
                $this->type = $type;
            }
        }
    }
    
    /**
    * Adiciona um valor a lista
    */
    public function add($val)
    {
        // verifica se o tipo sendo adicionado eh um objeto
        // e se o tipo do objeto eh diferente do tipo definido
        // para a lista
        if (is_object($val) && strtolower(get_class($val)) != $this->type) {
            // caso o tipo seja diferente, verifica se a lista foi criada
            // com a opcao de se utilizar subtipos do tipo (extend)
            if ($this->useExtend != true || !($val instanceof $this->type)) {
                // caso nao tenha, gera uma exception
                throw new InvalidGenericTypeException(sprintf('Invalid object type: %s, expected: %s', strtolower(get_class($val)), $this->type));
            }
        }
        
        // caso o tipo sendo adicionado nao seja um objeto
        // e seja diferente do tipo definido para a lista,
        // gera uma exception (tambem)
        if (!is_object($val) && gettype($val) != $this->type) {
            throw new InvalidGenericTypeException(sprintf('Invalid type: %s, expected: %s', get_class($val), $this->type));
        }
        
        // se chegou ate aqui, nao ha erros
        $this->values[] = $val;
        
        // retorna o valor sendo adicionado a lista
        return $val;
    }
    
    /**
    * Retorna o tamanho da lista
    */
    public function size()
    {
        // exatamente como imaginou no teste,
        // um simples sizeof
        return sizeof($this->values);
    }
}

5 – Testando
Depois de termos as implementações, já podemos testar:

$ phpunit TestGenericList.php
PHPUnit 3.0.6 by Sebastian Bergmann.

……….

Time: 00:00

OK (10 tests)

E tudo ok. Não é comum passar 100% logo na primeira implementação, mas tudo bem.

6 – Considerações
Algumas coisas que podemos notar:

- Antes mesmo de escrever a implementação da classe GenericList já tinhamos “pronto” nos testes o comportamento que desejavamos
- Todos os testes FALHAVAM antes da implementação da classe. E falhavam de duas formas: Primeiro porque não havia a classe e nem os métodos, então havia a falha de classe não encontrada. Segundo, por mais que tivessemos a classe e os métodos, mas os métodos não tivessem sido implementados, os testes iriam falhar. Este é o comportamento correto de um teste. É comum quando se começa a escrever testes (unitários) fazer com que eles passem antes mesmo de falhar.
- Escreva um teste para falhar e não para passar
- Em PHP não poderemos (não no 5, 6 e nem tão cedo, acredito) utilizar de forma “elegante”, como se faz em outras linguagens, a GenericList como parâmetro de um método, mas podemos emular isso:
java: public void showNomes(GenericList<Pessoa> pessoas)
c#: public void ShowNomes(GenericList<Pessoa> pessoas)
php: um leve “hack”
public function showNomes(GenericList $pessoas)
{
$pessoas->getType() == ‘pessoa’ || eval(’throw new InvalidGenericTypeException(”Expected GenericList”);’);
}
- Como escrevi ali antes, sabiamos o comportamento que desejamos para a nossa classe. Há um outro método de design que dá mais ênfase nisso. Veja:
behavior-driven.org
Behavior driven development

É isso ai. Mais, em breve.

Arquivos:
g.class.php
genericlist.class.php
invalidgenerictypeexception.class.php
TestGenericList.php





1, 2, 3 testando

16 11 2007

Muito ocupado nos últimos tempos, por isso a falta de notícias, links, etc…

Mas voltaremos ao normal.





PHP / refactoring: Como ? (Outra vez)

22 09 2007

Já havia  comentado aqui alguma coisa. Mas aqui encontramos um artigo muito legal sobre isso.

Apesar de não ser permitido, muitos beta-testers (e desenvolvedores) dessa “next generation IDE” tem comentado sobre as features da nova IDE da Zend. Também gostaria de falar sobre profiling, code coverage em testes unitários, debug e blablabla, mas não posso :) .





A importância da comunicação

27 07 2007

Mais um off-topic

falta_comunicao_desenvolvimento.jpg

Comunicação é uma das premissas do Extreme Programing que acredito ser a mais importante.

Esta imagem é muito utilizada, chega a ser um chavão para os “mais andados”. Vi ela 3 vezes neste mês e aproveitei para compartilhar, sempre tem gente que não a viu.
Aproveitando o off-topic, fica uma sugestão:

Haverá hoje uma apresentação sobre Scrum (o título é “Entendendo Scrum Para Gerenciar Projetos Ágeis” ):

http://www.egenial.com.br/betaEventos

A primeira apresentação que assisti neste ambiente foi exatamente uma “introdução” a XP, excelente por sinal
. É bem provável que a qualidade se mantenha, então fica a sugestão, se não tem alguma coisa suficientemente importante para fazer, vale a pena assistir, hoje, a partir das 20:30. Estarei por lá.

E parabéns aos que vem fazendo com que estas apresentações aconteçam (Carlos Eduardo & cia)





Visão Ágil – Revista Brasileira Sobre Processos Ágeis

24 07 2007

Visão Ágil é primeira revista brasileira dedicada a processos ágeis, seu principal objetivo, é fornecer um canal único e dinâmico para reunir todas das vertentes ativas no cenário nacional.Este espaço, é aberto a todas as tribos como: Extreme Programming, FDD, Scrum e outras técnicas ágeis correlacionadas.

Portanto, acesse a primeira edição desse projeto ousado e feito com muito carinho para todos os agilistas do Brasil.

Conteúdo muito interessante.
Para quem não segue nenhum processo de desenvolvimento de software ou segue algum dito “burocrático”, e tem vontade de conhecer algum processo “ágil”, vale uma lida.

Entre os artigos, podemos ler sobre XP, SCRUM, um artigo falando sobre “As Cinco Doenças do Gerenciamento de Projetos” e um sobre “Contrato de Escopo Negociável”.

Apesar de não se aprofundar muito nos assuntos, todos os artigos tem um conteúdo muito bom.

Veja mais em visaoagil.com





PHP5: Namespaces

21 07 2007

[PHP-DEV] Namespaces patch backport
De: “Timm Friebe” thekid@thekid.de
Para: “PHPdev” internals@lists.php.net
Data: Hoje 06:57:30Hi,
I’ve backported the namespaces patch to current CVS HEAD. Here it is:http://sitten-polizei.de/php/php5-namespaces.diff

I’ve tested it with the .phpt-tests Dmitry provided. Enjoy:)

- Timm


PHP Internals – PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

É certo que o patch não será aplicado ao na versão atual (5.2.3), mas quem sabe não se aplique em um eventual 5.3 ?

SE isso acontecesse, o que disse aqui certamente não teria o teor que teve.





PHP5 ? Blah!!!

17 07 2007

Alguns dias pra terminar de escrever isso, pode parecer batido:
gophp5.org

Leia.

Leu ? Ótima iniciativa, não ?

Será ?

Vejamos:

- Migrar um servidor de php4 para php5 não é apenas atualizar os pacotes e “plim”, esta pronto. Sempre há um custo.
- “As coisas instaladas” (softwares de quem contratou o serviço) provavelmente vão quebrar. Ponto!
- Aqueles que ainda não utilizam php5 para desenvolver provavelmente vão reclamar de “suas coisas quebradas”. Ponto!
- Quem migrou um servidor e teve problemas (não será apenas um, nem dois, nem três) vai se arrepender da escolha algum tempo depois.

Parece óbvio, ao menos para mim.

E qual o problema nisso tudo ?

PHP6.

Assim que tivermos todo mundo usando PHP5, feliz da vida, após o trauma da transição do PHP4 para o PHP5, com todas as coisas supostamente funcionando, e blablabla, teremos o PHP6, recém saido do forno, com suporte a namespaces, unicode e outras coisas interessantes mais (se não tivesse nada de interessante a mais, seria o PHP5.3, PHP5.4, …).

E ai, começamos a campanha “abaixo PHP5, viva PHP6″ ? E os custos ? E as “coisas quebradas” da (in)feliz migração PHP4/PHP5 ? E os arrependimentos ? E as reclamações ? E e e ???

Um tiro no pé! É o que acho da iniciativa e das constantes “pressões” na adoção do PHP5.

Não que ele seja ruim, longe disso. Mas se coisas não funcionarem, quando tivermos uma boa quantidade de gente desenvolvendo em PHP6, estaremos vendo cada vez mais Aqueles_Nomes_De_Classes_Gigantescos em PHP5 e o PHP6 estará fadado a ser ignorado por empresas de hosting (consequentemente milhares de programadores ?).

Só espero estar errado. E que venha PHP6!





Annotations (@QualquerCoisa) em PHP

15 07 2007

Havia lido algum tempo atrás sobre annotations em PHP, mas nada muito concreto.

Vi hoje uma apresentação (antiga, do phpconference) falando mais sobre isso:

Mais, aqui
Muito interessante, bem que poderia fazer parte do core do PHP





xml to mysql: Transformando um arquivo XML em queries SQL (e blablabla)

7 07 2007

xml to mysql: Como fazer o reverso indicado aqui: mysql to xml: Como transformar um resultado de uma query para XML ( de forma simples ) ( de forma simples )

Sugerido aqui, por Robertson Matos

Para o script, vamos utilizar um banco de dados de exemplo. O banco terá a seguinte estrutura:

-- criamos o banco de dados, caso ainda nao exista
CREATE DATABASE IF NOT EXISTS XML2MYSQL;

-- selecionamos o banco de dados
USE XML2MYSQL;

-- criamos a tabela se nao existir
CREATE TABLE IF NOT EXISTS exemplo (
    id_exemplo INT(11) NOT NULL AUTO_INCREMENT,
    descricao VARCHAR(32) NOT NULL,
    PRIMARY KEY(id_exemplo)
)ENGINE=INNODB;

O XML de exemplo é este:
demo.xml


<?xml version=“1.0″?>
<resultset>
    <line>
        <id_exemplo>1</id_exemplo>
        <descricao>Primeiro exemplo</descricao>
    </line>
    <line>
        <id_exemplo>2</id_exemplo>
        <descricao>Segundo exemplo</descricao>
    </line>
    <line>
        <id_exemplo>3</id_exemplo>
        <descricao>Terceiro exemplo</descricao>
    </line>
</resultset>

E o script é este:


<?php
    
// arquivo xml2mysql.php

    // definimos informacoes para conexao ao banco de dados:
    $banco   ‘xml2mysql’;             // nome do banco
    
$host    ‘localhost’;             // host
    
$usuario ‘root’;                  // usuario
    
$senha   ;               // senha
    
    // connectamos ao host e selecionamos o banco
    
mysql_connect($host$usuario$senha);
    
mysql_select_db($banco);

    // esta variavel sera a query utilizada para insercao dos
    // dados no banco, tendo o %d substituido pelo id_exemplo
    // e o %s substituido pela descricao
    
$query ‘insert into exemplo (id_exemplo, descricao) values (%d, ”%s”)’;
    
    
// carregamos o conteudo do arquivo XML
    
$xml file_get_contents(‘demo.xml’);
    
    
// transformamos o XML em um objeto, para que possamos trabalhar
    // de forma mais simples com ele
    
$sxml = new SimpleXMLElement($xml);
    
    
// aqui iteramos por todo o XML:
    // a cada iteracao, $line ira conter um objeto to tipo
    // SimpleXMLElement, sendo o equivalente a:
    //
    //  <line>
    //      <id_exemplo>1</id_exemplo>
    //      <descricao>Primeiro exemplo</descricao>
    //  </line>
    //
    
foreach ($sxml as $linhaAtual) {
        
// aqui vamos obter cada item do xml que seria referente
        // ao campo da tabela.
        // Necessario cast pelo fato de que a propriedade do objeto
        // tambem é um objeto do tipo SimpleXMLElement
        
$id        = (int) $linhaAtual->id_exemplo;
        
$descricao = (string) $linhaAtual->descricao;
        
        
// aqui preparamos a query para ser utilizada
        
$tmpQuery sprintf($query$id$descricao);
        
        
// exibimos a query que será executada
        
echo sprintf(‘Executando query: %s%s’$tmpQuery“\n”);

        // e aqui executamos a query
        
mysql_query($tmpQuery);
    }

Sem controle de erros, prevenção de sql injection, blablabla, apenas para ilustrar, como de costume.
Executando temos:

$ php xml2mysql.php
Executando query: insert into exemplo (id_exemplo, descricao) values (1, “Primeiro exemplo”)
Executando query: insert into exemplo (id_exemplo, descricao) values (2, “Segundo exemplo”)
Executando query: insert into exemplo (id_exemplo, descricao) values (3, “Terceiro exemplo”)

E conferindo no banco:

mysql> select * from exemplo;
+————+——————+
| id_exemplo | descricao |
+————+——————+
| 1 | Primeiro exemplo |
| 2 | Segundo exemplo |
| 3 | Terceiro exemplo |
+————+——————+
3 rows in set (0.00 sec)

É isso ai, valeu pela sugestão Robertson

Arquivos:
xml2mysql.php
xml2mysql.sql
demo.xml





PHP / refactoring: Como ? (Parte 2)

25 05 2007

Pois é, eu não sabia que teria parte 2, mas este é para ser uma continuação do post PHP / refactoring: Como ?.

Vejamos agora como modificar o nome de uma função e as chamadas para a mesma. O exemplo anterior com algumas modificações será utilizado:


<?php
// arquivo sample2.php

$foo   ‘foo’;
$hello “Ola $foo\n”;

// funcao foo() no comentario nao sera modificada

function foo()
{
    
// variavel $foo nao sera modificada
    
$foo “dentro de foo()\n”;
    echo 
$foo;
}

// exibimos $hello
echo $hello;

// observe que foo() e foo () sao diferentes: 
// foo() equivale a:
//      T_STRING        (foo)
//      (               (abre parenteses)
//
// enquanto foo () equivale a:
//      T_STRING        (foo)
//      T_WHITESPACE    (’ ’)
//      (               (abre parenteses)
//
// e por esse motivo deve ser tratado como diferente
foo ( );
?>

E a função com exemplo de uso:


<?php
// arquivo change_function_name.php

/**
 * Funcao que ira modificar o nome de uma funcao
 *
 * @param  array  $tokens  Array com os tokens a serem analisados
 * @param  string $oldName Nome da funcao que sera modificada
 * @param  string $newName Novo nome da funcao
 * @return string Codigo-fonte referente aos tokens fornecidos, com a 
 * funcao devidamente modificada
 */
function changeFunctionName($tokens$oldName$newName)
{
    
// variavel que ira conter o codigo-fonte a ser retornado
    
$ret ;

    // contador, marcara o indice do token em uso
    
$tokenIndex = -1;
    
    
// como $tokens e’ um array, utilizamos foreach para
    // passar por todos os seus itens
    
foreach ($tokens as $token) {
        
$tokenIndex++;
        
// quando se obtem os tokens de um arquivo, eles vem em um 
        // array contendo o numero do token e o valor ou em uma string,
        // contendo apenas o valor. Entao verificamos qual o caso.
        
if (!is_array($token)) {
            
$tokenName  false;
            
$tokenValue $token;
        } else {
            
$tokenName  token_name($token[0]);
            
$tokenValue $token[1];
        }

        // verificamos se o token atual pode ser considerado uma funcao
        
if ($tokenName == ‘T_STRING’) {
            
// obtemos os dois proximos tokens
            
$nextToken  $tokens[$tokenIndex 1];
            
$nnextToken $tokens[$tokenIndex 2];

            // aqui temos o seguinte:
            // se o proximo token for igual a ”(” E se o valor do token atual for igual
            // ao nome da funcao que queremos modificar…
            
$flag  = ($nextToken[0] == ‘(’ && $tokenValue == $oldName);
            
            
// … OU o proximo token for um espaco E o token apos o proximo for igual a ”(”
            // E o valor do token atual for igual ao nome da funcao que queremos modificar…
            
$flag |= (@token_name($nextToken[0]) == ‘T_WHITESPACE’ && $nnextToken[0] == ‘(’ && $tokenValue == $oldName);

            // … entao modificamos o valor do token,
            
if ($flag) {
                
$tokenValue $newName;
                
$ret .= $tokenValue;
                continue;
            }
        }
        
        
// se chegou ate aqui, significa que nao e’ um token que nos interessa, apenas pegamos
        // o valor do token e o adicionamos ao final do fonte a ser retornado
        
$ret .= $tokenValue;
    }
    
    
// retornamos o fonte
    
return $ret;
}

// exemplo de uso da funcao

// obtemos o conteudo do arquivo que iremos modificar
$arquivo file_get_contents(’sample2.php’);

// e utilizamos a funcao token_get_all para obter todos
// os tokens do arquivo. Observe que tudo no script e’
// tratado como sendo um token
$tokens  token_get_all($arquivo);

// modificamos foo() para bar()
$bla changeFunctionName($tokens‘foo’‘bar’);

echo $bla;

?>

Executando:

$ php change_function_name.php
<?php
// arquivo sample2.php

$foo = ‘foo’;
$hello = "Ola $foo\n";

// funcao foo() no comentario nao sera modificada

function bar()
{
// variavel $foo nao sera modificada
$foo = "dentro de foo()\n";
echo $foo;
}

// exibimos $hello
echo $hello;

// observe que foo() e foo () sao diferentes:
// foo() equivale a:
// T_STRING (foo)
// ( (abre parenteses)
//
// enquanto foo () equivale a:
// T_STRING (foo)
// T_WHITESPACE (’ ‘)
// ( (abre parenteses)
//
// e por esse motivo deve ser tratado como diferente
bar ( );
?>

Observe que a declaração da função foi modificada ( function bar ) e a chamada à função também foi modificada (bar ( ); ).
Ótimo, esta pronto ? Não…

Como bem sabemos, é possível executar funções de outras formas em PHP, como por exemplo, utilizando call_user_func, eval, variáveis utilizadas como funções ( $foo(); ), funções utilizadas como callback, …

Então, em uma implementação completa desta função, deveriamos nos atentar a estes fatos.
Para alguns casos, seria relativamente fácil criar uma implementação:
- Em eval, poderiamos utilizar a string que esta sendo executada e, recursivamente, chamar a função changeFunctionName para os tokens obtidos para esta string
- Em call_user_func / call_user_func_array, poderiamos verificar se o token atual é um T_STRING e o valor do token é ‘call_user_func’, desta forma. Se for, analisaria-se os tokens seguintes para ver se não teria relação com a função sendo renomeada;

Já em outros casos, seria necessário um pouco mais de malabarismos:
- Em variáveis utilizadas como funções, provavelmente precisariamos de um trackback das variáveis, para verificar se o valor dela não corresponde ao nome da função que desejamos renomear
- Utilizar um grande switch para verificar todas as funções builtin do PHP que utilizam funções como callback

De qualquer forma, para fontes onde não se utilize a função sendo renomeada de forma mais “avançada”, este exemplo deve funcionar.

change_var_name.php (exemplo anterior)
change_function_name.php





OFF: Netbeans GUI Builder

5 05 2007

Nunca gostei do eclipse.
Quando comecei a programar em java (há um tempo já) comecei com netbeans. Gostava muito dele, bem simples, organizado e vinha “com tudo” que eu precisava.

Cheguei a instalar e utilizar o eclipse durante um tempo, mas sempre achando o netbeans melhor. E em algum momento que não lembro quando, deixei de utilizar essas IDEs, utilizando editores mais simples e mais leves (sentia dor na alma quando utilizava kde+firebird+tomcat+eclipse/netbeans, por isso “abandonei”).

Quando passei a trabalhar mais intensivamente com PHP, voltei a utilizar o eclipse com plugins para habilitar desenvolvimento em PHP, e como trabalhava também com java, acabou que o eclipse voltou a tornar-se meu ambiente de desenvolvimento único. Era java e PHP no mesmo local. Simples assim.
E nesse tempo havia esquecido quase que completamente do netbeans, apenas acompanhando de longe o desenvolvimento do matisse, que era um “gui builder” em fase alpha dele.

Hoje vejo o estado que está esse “gui builder” e… Tirem 10 minutos e assistam:

netbeans 6 gui builder

Tão ou mais simples criar uma aplicação em java para desktop quanto o delphi (não, não o delphi4php :) )

Será que fazem isso no eclipse ?





Link: Comparação de IDES para desenvolvimento em PHP

5 05 2007

É um post antigo, mas bem interessante, onde é feita uma comparação entre Eclipse, Komodo, PHP Designer, PhpED, PHPEdit e Zend Studio:

Seven great PHP IDEs compared

Tinha idéia de escrever um post parecido, comparando também (se é que alguns desses podem ser comparados) o jdeveloper da oracle, com “Oracle PHP Extension for Oracle JDeveloper 10g”, o delphi4php, o pdt, o quanta, o kate, o kdevelop, o dreamweaver, o vim e o mcedit (este por ser o editor que uso atualmente : ) ).

Além desses, há outra dezena que poderia entrar na comparação / descrição, mas por não ter muito tempo pra isso, acho que vale a dica da comparação do link.