Ir para conteúdo

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

ronaldoalmeida

myframework

Recommended Posts

Pode até ser que haja perda de performance por abrir e fechar a conexão ao invés de mantê-la aberta... Mas por outro lado se manter aberta e ociosa pode perder usuários para o site. Ocorreu comigo no passado, por ter muitos usuários conectados ao mesmo tempo, esgotou o limite de conexões ao bd, e os usuários que entravam no site posteriormente, ficava sem ver conteúdo algum porque nao havia conexão com o bd. Então acredito que é preciso pesar as consequência... Eu acredito que há uma sobrecarga se uma página fizer 10 requisições e cada uma abrir e fechar a conexão com o bd, mas tbm há uma perda muito grande se mantiver a conexão aberta durante todas as 10 requisições e finalizar somente quando conclui-las. Pensando em números grandes de acesso simultâneos (meu caso), talvez seja melhor sobrecarregar o servidor que é dedicado e aguenta do que perder dinheiro por não exibir conteúdo ao usuário por falta de conexão ao bd.

 

Vou ter que dar uma pesquisada pra argumentar contra dessa vez, mas pense que frameworks como o Zend utiliza a abordagem que eu falei e eles são usados para aplicações gigantescas.

 

Como te falei anteriormente, eu fiz os testes sem o uso de passagem por referência e não deu certo, concluo que a mudança na versão 5 é para quando se usa o operador new e deseja atribuir o valor(objeto) para uma variavel com o operador '='. Me corrija se estiver errado.

 

É que não é passagem por referência, é passagem pro valor-referência, é meio estranho.

 

Por exemplo:

function foo(Object $bar) {
$bar = new Object();
}

Se eu faço uma atribuição sobre o elemento passado, ele não afetará seu valor fora do escopo da função foo.

 

Entretanto, se eu fizer algo assim:

function baz(Object $bar) {
$bar->setSomething('bla');
}

O objeto será alterado, mesmo fora do escopo da função. Faça o teste.

 

Basicamente, se você fizer uma atribuição sobre o parâmetro, ele se comportará como passagem por valor, se você invocar um método que altera o objeto, ele se comportará como referência. Se você atribuir o objeto a uma variável dentro do escopo da função, novamente, teremos ele se comportando como referência.

 

Vale lembrar que referência no PHP não é a mesma coisa que no C, por exemplo:

References in PHP are a means to access the same variable content by different names. They are not like C pointers; for instance, you cannot perform pointer arithmetic using them, they are not actual memory addresses, and so on [...]

 

Eu sei que poderia colocar os métodos da classe BancoDeDados na CRUD ou vice-versa, funcionaria da mesma forma. Mas o principio SRP no meu ponto de vista seria violado, não? Imaginemos que a classe BancoDeDados foi transferida para CRUD. Se pensar nas responsabilidade desta classe agora, no meu ponto de vista, teriamos conexão com banco de dados e manipulação de registros, embora sejam coisas próximas, as responsabilidade são distinta. Se eu precisar mudar alguma coisa na conexão que o CRUD usa, vou precisar alterar a classe CRUD, e se precisar alterar alguma operação sobre o registros (deletar, consultar, atualizar e inserir) vou mexer na mesma classe, não seria o ideal, seria bom separar essas responsabilidades. Novamente me corrija se eu estiver equivocado.

<br class="clear"> Pensa assim: CRUD não são operações sobre um banco de dados? Pra realizar qualquer uma dessas operações, você precisa de uma conexão. Se você está criando uma base genérica para o CRUD, supõe-se que você vai prever as possíveis soluções, ou seja, as chances de você ter que ir lá e fazer uma mudança são mínimas.

 

BancoDeDados tem um CRUD e DBTableGateway usa CRUD, mas referencia BancoDeDados, que vai retornar o CRUD para DBTableGateway utilizar. Se a função de BancoDeDados é unicamente fornecer um objeto CRUD pra DBTableGateway, qual a razão dela existir?

 

Pesquise um pouco sobre Injeção de Dependências (ou Inversão de Controle) para ver se você se convence.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Vou ter que dar uma pesquisada pra argumentar contra dessa vez, mas pense que frameworks como o Zend utiliza a abordagem que eu falei e eles são usados para aplicações gigantescas.

 

Essa questão é interessante... a implementação de conectar e desconectar foi algo que pensei ao trabalhar na classe CRUD- talvez visando o problema que tive no passado com max_user_connection. Mas pensando bem... o seu conselho é válido. Visto que essa implementação não está na PDOFactory, posso alterar como desejar. Eu vou implementar a CRUD de outra forma: Vou fazer a requisição de conexão somente quando não houver uma conexão ativa e vou tirar a desconexão dos métodos, assim, a conexão só será destruída quando for expressa de forma manual pelo método PDO::desconectar().

 

Dessa forma, dará para executar uma sequência de requisições ao banco de dados e desconectar logo após essa conclusão. Até poderia manter o conectar e desconectar e usar prepare() e commit(), mas como não são todos os SGBD que aceitam, então nem vou pensar em implementar isso, fazer dessa forma manual é melhor.

 

 

 

É que não é passagem por referência, é passagem pro valor-referência, é meio estranho.

 

Testei os exemplos, realmente funcionam como você mencionou e até agradeço pois aprendi mais sobre valor-referência do PHP. Mas, no nosso exemplo real, não se aplica o valor-referência. Pelo fato de estarmos recebendo o objeto por parâmetro e estarmos armazenando-o numa propriedade da classe, é preciso indicar que o valor da propriedade será por referência.

 

Código da classe CRUD para lembrarmos da intenção original:

   public function __construct(PDOFactory &$pdo)
   {
       //define a propriedade com o valor por referência, garantindo que sempre que houver alterações na variavel, a propriedade automaticamente apontará para o novo valor.
       $this->PDO = &$pdo;
   }  

 

 

Exemplo - sem indicar referência:

class Test
{
   public $storeObject;

   public function foo($bar)
   {
       $this->storeObject = $bar;
   }

   public function getObject()
   {
       return $this->storeObject;
   }
}

//variavel recebe uma instancia de stdClass
$objectTest = new stdClass();


//usa a classe Test para armazenar em sua propriedade o valor da variavel objectTest, mas queremos que a propriedade aponte para o mesmo valor da variavel caso ela seja alterada fora do escopo da classe.
$classTest = new Test();
$classTest->foo($objectTest);

//alteração do valor da variavel fora do escopo da classe
$objectTest = new Directory();

//a propriedade da classe não está apontando para o mesmo lugar na memoria da variavel objectTest, indicando que não foi passado por referência.
echo get_class($classTest->getObject());

 

Note que a saída será stdClass e não uma instância de Directory (alterada posteriormente). A intenção original (na classe BancoDeDados) era de se alterarmos o driver de banco de dados em tempo de execução fora da classe CRUD, a CRUD apontaria para o driver correto.

 

 

Exemplo com referência

 

 

class Test
{
   public $storeObject;

   public function foo(&$bar)
   {
       $this->storeObject = &$bar;
   }

   public function getObject()
   {
       return $this->storeObject;
   }
}

//variavel recebe uma instancia de stdClass
$objectTest = new stdClass();


//usa a classe Test para armazenar em sua propriedade o valor da variavel objectTest, mas queremos que a propriedade aponte para o mesmo valor da variavel caso ela seja alterada fora do escopo da classe.
$classTest = new Test();
$classTest->foo($objectTest);

//alteração do valor da variavel fora do escopo da classe
$objectTest = new Directory();

//a propriedade da classe está apontando para o mesmo lugar na memoria da variavel objectTest.
echo get_class($classTest->getObject());

 

 

Agora sim, a saída será uma instância de Directory, mesmo alterando fora do escopo da classe, temos o valor correto desejado.

 

 

Pensa assim: CRUD não são operações sobre um banco de dados? Pra realizar qualquer uma dessas operações, você precisa de uma conexão. Se você está criando uma base genérica para o CRUD, supõe-se que você vai prever as possíveis soluções, ou seja, as chances de você ter que ir lá e fazer uma mudança são mínimas.

 

BancoDeDados tem um CRUD e DBTableGateway usa CRUD, mas referencia BancoDeDados, que vai retornar o CRUD para DBTableGateway utilizar. Se a função de BancoDeDados é unicamente fornecer um objeto CRUD pra DBTableGateway, qual a razão dela existir?

 

Pesquise um pouco sobre Injeção de Dependências (ou Inversão de Controle) para ver se você se convence.

 

 

Conheço o principio, até mesmo usei ele na classe CRUD (no construct), mas o método BancoDeDados::setConexao() me fez pensar em criar a classe BancoDeDados a fim de separar esse método (setConexao()) das operações CRUD. Mas, sem dúvida, você tem razão, é melhor eliminar a classe BancoDeDados e simplesmente passar o método para a CRUD. A criação da classe BancoDeDados trouxe muito trabalho extra se for pensar bem... Tive que acoplar um CRUD à ela, implementar a CRUD para receber por referência o driver de banco de dados tornando mais complexa o seu entendimento... Não tem dúvida que é melhor passar a usar somente a CRUD :)/>

 

Já vou fazer as alterações heheheh

 

 

A primeira questão desse post (valor-referência) será eliminado, visto que BancoDeDados não mais existirá... mas a discussão de alto nível (pelo menos pra mim :P/>) foi muito boa. Aprendi, analisei e outros poderão aprender tbm...

 

-------

 

 

Eu vou fazer aqui todas as mudanças que fomos abordando na discussão e vou postar o código-fonte final com as alterações feitas. Se for útil à alguém, poderão usar.

 

Eu vou fazer as alterações tbm nos diagramas uml... depois eu posto e se tiver mais sugestões, fiquem a vontade para expressarem.

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.