Ir para conteúdo
Fórum Script Brasil
  • 0

(Resolvido) Dúvida sobre o padrão DAO do Design Patterns


Rafael Laurindo

Pergunta

Galera, desta vez o assunto é mais sério. Design Patterns. De acordo com o padrão DAO (Data Access Object), devo ter uma classe para transferencia de dados que contenham todos os atributos de uma tabela do banco de dados como private, sendo assim, deve haver um método público para cada atributo, para defini-los bem como acessa-los. A dúvida é: eu preciso realmente de um para cada? A dúvida, é por ter visto assim em exemplos, e me deu vontade de fazer os métodos __set() e __get() mais genéricos de acordo com o exemplo à saber:

class Teste{
      
      private
          $teste,
          $teste2;
  
      public function __set($attName, $value){
          $this->$attName = $value;
      }
      
      public function __get($attName){
          return $this->$attName;
      }
  }
  
  $t = new Teste();
  $t->__set('teste', 'Rafael');
  $t->__set('teste2', 'oi');
  echo $t->__get('teste2'); //oi
  echo $t->__get('teste'); //Rafael

Isso também é correto? Eu achei que fosse porque economizou código, o foco do DAO é separar as regras de negócio dos métodos de acesso ao banco, ficando assim as classes, mais fáceis de serem reutilizadas, bem como o código arrumado. Mas se puderem opinar eu agradeceria muito.

Editado por Rafael Laurindo
Link para o comentário
Compartilhar em outros sites

8 respostass a esta questão

Posts Recomendados

  • 0

Salve,

Não ficou muito interessante este código.

Vamos dizer que tenho a tabela cliente que possui 10 colunas. Segundo sua descricao ao localizar a informação sobre 1 determinado registro devo retornar uma classe com 10 membros privados. Se para cada membro privado eu tenho que emular metodos para realizar o encapsulamento, seu código não atende a necessidade da classe.

Abraços

Link para o comentário
Compartilhar em outros sites

  • 0

Veja um exemplo abaixo de fazer encapsulamento dinamico no PHP.

Nota: Isso é a maior gambiarra que existe em uma linguagem de programação

<?php
/**
 *
 * @version 1.0
 * @author Wellington Rodrigues <wellingtonbr@gmail.com>
 */
class Cliente
{
    /**
     * @var array
     */
    private $fields;        
    /**
     *  __construct()
     *
     * @version 1.0
     * @author Wellington Rodrigues <wellingtonbr@gmail.com>
     * @return void
     */
    public function __construct()
    {
        $this->fields = array();
    }
    /**
     *  __call()
     *
     * @version 1.0
     * @author Wellington Rodrigues <wellingtonbr@gmail.com>
     * @param string $name
     * @param array $arguments
     * @return mixed
     */    
    public function __call( $name, array $arguments )
    {    
        if( preg_match('/^(g|s)+et/i', $name ) )
        {
            $property = strtolower(preg_replace('/^(g|s)+et/i', '', $name));            
            if( preg_match('/^set/i', $name ) )
            {            
                $this->fields[$property] = $arguments[0];
            }
            else if( preg_match('/^get/i', $name ) )
            {
                return $this->fields[$property];
            }
        }
        else
        {
            throw new Exception('O método '.$name.' não localizando na classe '.__CLASS__);
        }
    }
}
Exemplo de uso
//CRIA INSTANCIA
$cliente = new Cliente( array('nome') );
//CONFIGURA NOME 
$cliente->setNome('ursolouco');
printf('<pre>%s</pre>', print_r($cliente->getNome(),true));
//CONFIGURA IDADE
$cliente->setIdade(57);
printf('<pre>%s</pre>', print_r($cliente->getIdade(),true));

abraços

Link para o comentário
Compartilhar em outros sites

  • 0
Não ficou muito interessante este código.

Vamos dizer que tenho a tabela cliente que possui 10 colunas. Segundo sua descricao ao localizar a informação sobre 1 determinado registro devo retornar uma classe com 10 membros privados. Se para cada membro privado eu tenho que emular metodos para realizar o encapsulamento, seu código não atende a necessidade da classe.

Na verdade, esse era só um exemplo, a classe deveria ter os mesmo atributos que a tabela do banco, é como se essa classe representasse uma tabela com apenas dois atributos, daí eu não precisaria fazer os métodos "setTeste", "setTeste2", "getTeste", "getTeste2", resolvendo assim com o __set($property, $value) e o __get($property), mas desse jeito eu teria que definir todos os atributos antes. Com esse novo jeito é totalmente dinâmico.

Você criou uma forma para se criar os métodos para criar propriedades dinamicamente, e seus métodos, "get" e "set". Gostei muito, que economia de código. Bom, desculpe a ignorância, mas desse jeito, eu nunca mais precisarei modelar uma classe tipo Transfer Object, com todos os seus atributos? Visto que nunca precisarei defini-los antes, nem os métodos para defini-los e recupera-los. É isso mesmo? Caso sim, muito obrigado. Vou comenta-lo para a galera desfrutar também. Se não, não é qualquer um que o entenderá.

<?php
/**
* @version 1.0
* @author Wellington Rodrigues <wellingtonbr@gmail.com>
*/

//essa classe tem a importancia de criar, definir e recuperar seus atributos. Não incluindo métodos de acesso a base de dados. Devendo estes ficarem em outra classe.
class Cliente
{
    private
        $arr_property;

    public function __construct(){
        //da o poder a $arr_property de ser um array, podendo criar/acessar índices e receber/recuperar valores
        $this->arr_property = array();
    }


    //o método __call() é executado toda vez que tentamos chamar um método da classe, sendo passado para ele como parâmetro, o nome do método e seus argumentos
    //o array está especificando o tipo do argumento que será usado no método
    public function __call($methodName, array $arguments)
    {
        //verifica se $methodName começa com set ou get
        if( preg_match('/^(g|s)+et/', $methodName))
        {
            //troca set ou get de $methodName por '' tranformando method na palavra restante, toda em minúscula. Ex.: setName = name
            $property = strtolower(preg_replace('/^(g|s)+et/','', $methodName));
            if(preg_match('/^set/', $methodName)){
                //Atribui o primeiro valor do array "arguments" ao array $arr_property. Nesse caso, é o único que interessa
                $this->arr_property[$property] = $argument[0];
            }
            else if( preg_match('/^get/', $method ) )
                return $this->arr_property[$property];
        }
        else{
            //Para o processamento, e instancia a classe "Exception" passando a menssagem abaixo para o seu método mágico "__construct()"
            throw new Exception('O método '.$methodName." não existe em \"".__CLASS__."\"");
        }
    }
}

//cria a instancia
$cliente = new Cliente();

//cria dinâmicamente os métodos, get e set bem como as propriedades Nome e Idade, e seus respectivos valores
$cliente->setNome('ursolouco');
$cliente->setIdade(27);

echo $cliente->getNome() . "<br />";
echo $cliente->getIdade();

Explicando as expressões de validação:

/^ : início

(g|s) : verifica se a primeira letra começa com g ou s

+ : concatena

+et: verifica se tem "et" depois da expressão anterior. Ex.: nesse caso, s + et = set ou g + et = get

/ : fim

Galera, esse código é do Welligton, eu só modifiquei algumas coisas. ;) Akeleabrass.

Editado por Rafael Laurindo
Link para o comentário
Compartilhar em outros sites

  • 0

Brother, veja alguns comentários abaixo:

Na verdade, esse era só um exemplo, a classe deveria ter os mesmo atributos que a tabela do banco, é como se essa classe representasse uma tabela com apenas dois atributos, daí eu não precisaria fazer os métodos "setTeste", "setTeste2", "getTeste", "getTeste2", resolvendo assim com o __set($property, $value) e o __get($property), mas desse jeito eu teria que definir todos os atributos antes.

Se for para fazer o que você descreveu acima, porque não ultilizar stdClass com membros publicos ?

Você criou uma forma para se criar os métodos para criar propriedades dinamicamente, e seus métodos, "get" e "set". Gostei muito, que economia de código. Bom, desculpe a ignorância, mas desse jeito, eu nunca mais precisarei modelar uma classe tipo Transfer Object, com todos os seus atributos?

Bom, vai depender da modelagem e conceito aplicado no sistema mas poderia ser um modelo de classe para ser realizado como 'Mensagem' (troca) entre objetos.

Visto que nunca precisarei defini-los antes, nem os métodos para defini-los e recupera-los. É isso mesmo? Caso sim, muito obrigado.

Sim, seria isso mesmo. Eu desenvolvi este código devido a uma determinada situação em que precisei dar manutenção em um grande sistema e estava com muita preguiça na hora.

Vou comenta-lo para a galera desfrutar também. Se não, não é qualquer um que o entenderá.

Seja humilde! Deixe o código com os devidos crédito do autor (como recomenda a GPL) e apenas gere exemplos de uso, objetivo da classe e como dar manutenção na mesma.

Observação:

1 - Como mencionado anteriormente, isso é gambiarra, mais pra frente você verá isso.

2 - O padrão de projeto DAO tem outro conceito, vá mais afundo ;-)

Abraços

Link para o comentário
Compartilhar em outros sites

Participe da discussão

Você pode postar agora e se registrar depois. Se você já tem uma conta, acesse agora para postar com sua conta.

Visitante
Responder esta pergunta...

×   Você colou conteúdo com formatação.   Remover formatação

  Apenas 75 emoticons são permitidos.

×   Seu link foi incorporado automaticamente.   Exibir como um link em vez disso

×   Seu conteúdo anterior foi restaurado.   Limpar Editor

×   Você não pode colar imagens diretamente. Carregar ou inserir imagens do URL.



  • Estatísticas dos Fóruns

    • Tópicos
      152,2k
    • Posts
      652k
×
×
  • Criar Novo...