Mockando funções do PHP

July 2, 2008

O phpunit é um framework para testes unitários em PHP. Esse framework inclui funcionalidades para utilização de mocks. No entanto, temos uma limitação pois não é possível mockar funções do PHP. Nesse post vou mostrar um possível workaround para esta situação.

Vamos supor o código abaixo:

public function get($params) {

    // A partir dos $params passados, montamos uma $url

    return file_get_contents($url);
}

O código acima recebe um array de parâmetros. A partir dele, monta a url de um webservice REST. Por fim, faz um HTTP GET nessa url e retorna o xml recebido. A responsabilidade deste método é montar a url corretamente a partir dos parâmetros recebidos. Este é o comportamento que deve ser testado. O GET é feito pela função file_get_contents.

Idealmente queremos mockar a função file_get_contents. Mocks são usados com diversas finalidades. Neste exemplo, as duas principais motivações são: isolar o código de forma a só testar uma pequena unidade (montagem da url corretamente); e não fazer chamadas a um webservice real (por exemplo para não sobrecarregar um ambiente de produção ou porque o webservice não existe no ambiente de desenvolvimento.).

Já que não é possível mockar funções do PHP, como podemos mockar file_get_contents? Uma possível solução é criarmos uma classe cuja única responsabilidade é chamar esta função:

class FileGetContents {

    function file_get_contents($url) {
    	return file_get_contents($url);
    }

}

O código que queremos testar fica como abaixo. Note que uma instância de FileGetContents é injetada via construtor:

function ClienteHttp($fileGetContents) {
    $this->fileGetContents = $fileGetContents;
}

public function get($params) {
    // A partir dos $params passados, montamos uma $url

    return $this->fileGetContents->file_get_contents($url);
}

E podemos mockar a classe FileGetContents no nosso teste:

/**
 * @test
 */
public function deveria_chamar_webservice_com_url_correta() {
    $urlEsperada = "http://url.esperada";
    $fileGetContents = $this->getMock('FileGetContentsMock',array('file_get_contents'));
    $fileGetContents->expects($this->once())
    ->method('file_get_contents')->with($this->equalTo($urlEsperada))

    $clienteHttp = new ClienteHttp($fileGetContents);
    $parametros; // array de parâmetros que devem resultar na $urlEsperada
    $clienteHttp->get($parametros);
}

Alguns podem argumentar – corretamente – que a classe FileGetContents não é testada. Mas se levarmos em conta que ela simplesmente delega para uma outra função, a desvantagem não é tão significativa assim. Vale enfatizar a importância de que essa classe não tenha nenhum outro comportamento. Caso contrário, a falta de testes já não seria mais aceitável.


Falando em Java 2008

May 20, 2008

No último domingo estive no Falando em Java 2008. Foi um evento excelente, muito bem organizado pelo pessoal da Caelum. Na minha opinião os destaques foram:

  • A apresentação sobre Domain-Driven Design (DDD) do Sérgio Lopes. No dia anterior eu tinha participado de um workshop sobre DDD bastante interessante. Mas essa apresentação foi simplesmente show. No pouco tempo disponível – apenas 40 minutos – o Sérgio conseguiu passar o que é a essência de DDD: foco no domínio para resolver o problema; resgate da Orientação a Objetos; utilização da Linguagem Ubíqua, onde os mesmos termos utilizados na conversa com o cliente apareciam no modelo expresso em código. Fez isso usando um exemplo prático, onde a partir de uma conversa com o cliente implementava o sistema que este queria. Excelente!
  • A palestra do Fabio Kung sobre JRuby on Rails. O Kung deu uma aula sobre Ruby, JRuby e Rails. O mais interessante foi o final, onde ele mostrou que, apesar de JRuby on Rails (assim como Ruby MRI on Rails) ser lento e ter seus problemas para deploy em produção, a versão 3 do GUJ (feita em JRuby on Rails) consegue atender diversas vezes mais requisições por segundo do que a versão atual, em java.
  • A presença do Emmanuel Bernard, líder de diversos projetos do Hibernate. O Emmanuel fez duas apresentações. A primeira foi sobre a versão 2.0 do Java Persistence API (JPA). Basicamente eles estão incluindo nesta nova versão diversas funcionalidades que já existem no Hibernate e em outras ferramentas de ORM. A segunda foi sobre o Hibernate Search, uma ferramenta que utiliza o Apache Lucene e possibilita full text search de modelos de domínio persistentes. Muito interessante!

Workshop de Modelagem Ágil e DDD

May 20, 2008

Nos dias 16 e 17/05 estive em São Paulo para um workshop de Modelagem Ágil e DDD, organizado pela Fratech.

A parte de Modelagem Ágil começou com uma explicação mais teórica: modelos ágeis servem para facilitar a comunicação e não substituir a comunicação face a face; modelos devem ser criados e mantidos somente quando trouxerem valor real para o cliente; modelo não é a mesma coisa que documentação. Depois foram apresentados os conceitos de UML em Cores e Mind Map Modeling (M3). Minha impressão é que esses conceitos vão contra o que a modelagem ágil sugere. Estão mais para documentação do que modelagem. Não acredito que eles favorecem a utilização de abordagens ágeis na modelagem. O único conceito apresentado que, para mim, tem a ver com modelagem ágil é o AgileDraw, que nada mais é do que uma formalização dos rabiscos e rascunhos que fazemos nos quadros brancos, como bem disse o Bruno Carvalho.

Já a apresentação sobre Domain-Driven Design (DDD) foi bem mais interessante. O nível técnico em geral foi bem elevado assim como o nível das discussões. Alguns participantes já tinham um bom conhecimento sobre o assunto e a troca de experiências foi bastante produtiva.

Além disso, tive a oportunidade de conhecer diversas pessoas interessantes. Pena não termos conseguido marcar um chope. Na próxima não pode faltar!


“Modelagem Ágil e DDD” e “Falando em Java 2008″

May 12, 2008

Nesse próximo final de semana estarei em São Paulo para 2 eventos, junto com Vitor Pellegrino e Bruno Carvalho. O primeiro é um workshop de Modelagem Ágil e Domain-Driven Design que vai acontecer na sexta e sábado (dias 16 e 17). O segundo é o Falando em Java 2008 da Caelum, que acontece no domingo (dia 18). Neste evento, vamos estar acompanhados também do Guilherme Chapiewski.

Depois vou postar aqui as minhas impressões desses 2 eventos que prometem!


POJOs

March 4, 2008

Ultimamente tenho notado em listas de discussão, blogs, etc., pequenas confusões em relação ao termo POJO.

Algumas pessoas acham que POJO é sinônimo de JavaBean. Não é. JavaBean é uma especificação de um modelo de componentes. Os beans são componentes de software reutilizáveis que podem ser manipulados por ferramentas visuais para a criação de componentes compostos, applets, aplicações, etc.

Como um construtor público sem parâmetros e gets/sets públicos para os atributos são requisitos necessários (mas não suficientes) para um objeto atender à especificação JavaBean, alguns acham que POJO é sinônimo de objetos com construtores públicos e gets/sets para os atributos. Não é.

O termo foi criado por Martin Fowler, Rebecca Parsons e Josh MacKenzie e significa Plain Old Java Object ou Simples e Velho Objeto Java. Segundo o próprio Fowler, o termo foi criado ao preparem uma palestra para uma conferência em setembro de 2000. Nessa palestra eles mostravam diversos benefícios de se utilizar objetos comuns, simples, no lugar de algo mais pesado como EJBs, para implementar lógica de negócios. Eles não entendiam porque as pessoas tinham resistência em utilizar tais objetos comuns para lógica de negócios e chegaram a conclusão de que isso acontecia pois estes objetos não tinham uma denominação de efeito, que causa impacto. Então, criaram POJO.

Ou seja, um POJO nada mais é que um objeto simples, que não depende de implementar interfaces ou herdar de classes de algum framework externo. Não é, necessariamente, um JavaBean (mas pode ser). Não é, necessariamente, um objeto que tem getters e setters públicos para todos os seus atributos (mas pode ser).


Qi4j

November 27, 2007

Hoje estava lendo sobre o Qi4j que, como informado na página inicial do mesmo, trata-se de um framework para desenvolvimento de aplicações centrados no domínio, utilizando conceitos evoluídos de AOP, DI e DDD. Trata-se de uma implementação em Java de algo conhecido como Composite Oriented Programming.

O objetivo desse framework parece com o de vários outros: deixar o desenvolvedor se concentrar no modelo de domínio do sistema – que é onde está o valor do software – sem se preocupar com o resto, como detalhes técnicos de infra-estrutura.  Para isso ele utiliza o tal do Composite Oriented Programming, um paradigma radicalmente diferente. Vale a pena dar uma olhada no site para entender melhor do que se trata.

A implementação ainda se encontra num estado instável mas parece bastante promissor. Eu certamente vou acompanhar de perto sua evolução.


Como um modelo de dados pode acabar com a orientação a objetos de um sistema

November 21, 2007

Como já mencionei anteriormente, o cliente utiliza (e obriga a empresa onde eu trabalho a utilizar) o RUP como metodologia de desenvolvimento, mas que na verdade é um processo em cascata. Assim, temos que gerar um modelo de dados completo logo no início do projeto. Mudanças posteriores nesse modelo são burocráticas e demandam tempo para serem aprovadas. Esse tipo de coisa tem vários problemas conhecidos e já amplamente debatidos em outros lugares.

Mas um problema adicional que tenho observado com essa abordagem é que por causa dela o sistema perde características de orientação a objetos. O que acontece é que a equipe de desenvolvimento fica muita “amarrada” a esse modelo de dados e utiliza-o como referência na hora de criar as classes. Assim, conceitos de OO não são usados adequadamente. O código criado fica com uma relação de 1:1 entre classes e tabelas.

Vou explicar com um exemplo. Suponha que temos uma entidade qualquer que tenha 3 tipos diferentes: A, B e C. Uma modelagem de dados pode prever uma tabela Entidade com uma coluna TipoEntidade para representar isso. Já em termos de classe, idealmente teríamos uma classe “pai” – Entidade – e 3 classes herdando de Entidade: EntidadeA, EntidadeB e EntidadeC. No entanto, ao criar as classes olhando para o modelo de dados, é comum os desenvolvedores se fixarem demais nisso e criar uma única classe Entidade com um atributo tipoEntidade. O código fica, dessa forma, com vários if’s para lidar com comportamentos específicos de cada tipo, quando o mais correto seria ter esse código nas respectivas subclasses.

Não deve haver, necessariamente, uma correspondência tão direta entre tabelas e classes assim. Mas, para alguns, fica difícil ter uma mente mais aberta, quando o modelo de dados já está todo definido e sendo usado como referência para tudo o que é feito depois.

Na minha monografia, estou pesquisando como adaptar práticas sugeridas pelos métodos ágeis para funcionar na realidade da empresa onde trabalho. Idealmente, o design seria feito de forma evolutiva, em ciclos curtos e com muito feedback do cliente. Mas isso não é possível, pelo menos não imediatamente (pretendo na monografia sugerir ações que ajudem a mudar a mentalidade do cliente – mas isso é processo lento e gradativo). O cliente nos obriga a gerar o modelo de dados completo logo no início do projeto.

Uma solução para evitar essa falta de conceitos OO no sistema seria fazer uma modelagem de classes antes do modelo de dados. Ou seja, ainda teríamos o problema de fazer o design todo no início, mas pelo menos o design seria mais orientado a objetos. A partir do modelo de classes seria gerado o modelo de dados, sempre tendo em mente que não há necessidade de uma correspondência 1:1 entre tabelas e classes.