Permanecendo OO e testável ao trabalhar com um banco de dados

16

Quais são algumas estratégias de POO para trabalhar com um banco de dados, mas para manter as coisas testáveis? Digamos que eu tenha uma classe de Usuário e meu ambiente de produção funcione no MySQL. Vejo algumas abordagens possíveis, mostradas aqui usando PHP:

  1. Passe um $ data_source com interfaces para load()e save(), para abstrair a fonte de dados de back-end. Ao testar, passe em um armazenamento de dados diferente.

    $ usuário = novo usuário ($ mysql_data_source);
    $ user-> load ('bob');
    $ user-> setNickname ('Robby');
    $ usuário-> save ();
    
  2. Use uma fábrica que acesse o banco de dados e passe a linha de resultados ao construtor do Usuário. Ao testar, gere manualmente o parâmetro $ row ou zombe do objeto em UserFactory :: $ data_source. (Como posso salvar as alterações no registro?)

    class UserFactory {
        static $data_source;
    
        public static function fetch( $username ) {
            $row = self::$data_source->get( [params] );
    
            $user = new User( $row );
            return $user;
        }
    }
    

Eu tenho Design Patterns e Clean Code aqui ao meu lado, mas estou lutando para encontrar os conceitos aplicáveis.

Annika Backstrom
fonte

Respostas:

11

Então, o que você quer entender é Patterns of Enterprise Application Architecture de Martin Fowlers (ele também fornece um catálogo em seu site aqui ).

Nele, ele descreve vários padrões para abstrair o acesso a dados. A primeira abordagem que você descreve é ​​o Active Record . Sua segunda abordagem é semelhante ao Table Data Gateway .

Uma abordagem ainda melhor é usar um O / RM para remover a necessidade de escrever o código de acesso a dados manualmente. Não uso o PHP desde que estávamos preocupados com o Y2K, mas a wikipedia tem uma lista de opções para você . Eu não sei se eles são bons. No entanto, posso lhe dizer algumas coisas para procurar em um O / RM:

  • Ignorância de persistência : o O / RM não deve forçar seus objetos de negócios a derivar de uma interface / classe específica para participar da estratégia de acesso a dados.
  • Mapeamento de relacionamento : você deve poder mapear relacionamentos entre seus objetos (um cliente tem pedidos, pedidos têm itens de linha, itens de linha têm um produto etc.)
  • Mapeamento hierárquico : você deve conseguir mapear hierarquias de classes para o banco de dados.
  • Suporte à sintaxe / critério de consulta : você deve ser capaz de criar uma consulta em tempo de execução em termos de seus objetos, não em termos de banco de dados, e o O / RM deve converter e executar a consulta no banco de dados. Pontos extras se a consulta for uma cadeia fortemente tipada em vez de uma sequência.

Existem outros fatores a serem considerados, mas esses são alguns dos mais importantes. Espero que isto ajude.

Michael Brown
fonte
6

IMHO, depende do que você deseja testar; se quiser testar sua lógica de negócios, você deve stub / mock ( Martin Fowler ) acesso a seus dados para que sua primeira sugestão seja um bom começo. Essa questão de stackoverflow fornece um bom exemplo de C # (tentei encontrar alguns exemplos de PHP, mas não consegui encontrar nenhum).

Se você deseja testar o acesso a dados em si, ele não é mais chamado de teste de unidade, mas de teste de integração. Leia aqui para obter algumas orientações gerais, esta questão do stackoverflow também possui alguns links interessantes.

Se você quiser testar a lógica do procedimento armazenado em seu banco de dados, consulte xUnit TestPattern

Espero que isto ajude

KeesDijk
fonte
2

Esta não é necessariamente uma resposta imediatamente útil, mas se você está realmente preocupado com a testabilidade do banco de dados, deve analisar como isso é feito no Ruby on Rails. Até onde eu sei, ninguém cobriu o tópico de maneira melhor ou mais intuitiva.

Adam Crossland
fonte
2
O Ruby on Rails implementa o padrão Active Record por padrão. Poderia também fornecer um link: en.wikipedia.org/wiki/Active_record_pattern
Spoike
0

Eu recomendo que você verifique a solução Symfony Framework para esse tipo de problema. Symfony é um framework php OO com testes funcionais.

Aqui está um link , eles usaram algo parecido com o que você está pensando.

guiman
fonte