Desenvolvimento

Gravatar de Julio Greff Julio Greff Tópico publicado em
22/12/2009, 11:40:32

[v0.3] Problemas a serem resolvidos

Nada melhor do que usar o framework pra descobrir os problemas que ele tem. E como tenho tirado o máximo possível do Spaghetti* nos últimos projetos, acabei encontrando vários problemas que têm me incomodado bastante, e são coisas que merecem um cuidado especial. Alguns deles são fáceis de resolver, só adicionar uma coisa, mudar outra de lugar, mas algumas mexem em algumas coisas que talvez possam incomodar mais do que se não fossem mexidas. Então precisamos de boas idéias pra todas elas ;)

Colisão de Helpers e Variáveis

Quando o nome de um helper colide com o nome de uma variável, o helper torna-se {$helper}_helper. Nada mal, a menos que eu use esse helper em um layout, e eu defina uma variável de mesmo nome em apenas uma página. Chego à conclusão de que ou as variáveis ou os helpers não deviam estar no escopo "global".

A proposta, inicialmente, é colocar os helpers em View::helpers, ou as variáveis em View::data, e usar View::__set() e View::__get() para chamá-las em View::{$var}. Preciso de opiniões sobre.

Helpers devem ser definidos na view, e não no controller

O controller não precisa saber quais helpers precisam ser carregados na view, ela precisa se encarregar disso sozinha. E, na verdade, o usuário também não deveria saber quais helpers ele deve carregar pra coisa funcionar, a view deveria se encarregar disso também.

A proposta inicial, usando a idéia do item anterior, é usar um objeto HelperCollection com um método HelperCollection::__get() em View::helpers. Assim, a view carregaria helpers automaticamente.

Isso deixaria a coisa mais verbosa na view:

$this->helpers->html->link()

Outra alternativa seria usar View::__get() para chamar helpers assim:

$this->html_helper->link()

Ainda não me agrada muito. Idéias são bem vindas.

Carregar Componentes e Models dinamicamente

Definir componentes e models em Controller::components e Controller::uses é anti-produtivo e carrega coisas demais quando não deveria. Por exemplo, eu preciso usar o SwiftMailerComponent em apenas uma página, mas não posso desabilitar o AuthComponent e o AccessControlComponent que são usados em todas as páginas. O mesmo acontece com models que são usados em apenas uma action.

A proposta é criar dois métodos: Controller::loadComponent() e Controller::loadModel(). Não sei se existe alguma solução melhor pra isso, mas de qualquer maneira estamos abertos a idéias.

Esses são os problemas que me vêm à idéia agora. Assim que eu lembrar de mais alguns, volto a postar pra discutirmos.

Gravatar de Klawdyo Klawdyo Resposta publicada em
22/12/2009, 12:44:40

[v0.3] Problemas a serem resolvidos

Os dois primeiros nunca me causaram problemas.
Já esse terceiro é bem comum, principalmente na parte dos components, pois quando eu vou usá-lo somente em uma view, preciso carregá-lo no controller inteiro.

Sobre o terceiro item, poderia usar o método mágico __get() no controller que verificaria pela nomenclatura se trata-se de um model, component, helper, etc, e carregaria o objeto requerido.

Ao chamar

sm = $this->SwiftMailerComponent;

__get() identifica que trata-se de um component e o carrega.

Gravatar de Julio Greff Julio Greff Resposta publicada em
22/12/2009, 13:16:38

[v0.3] Problemas a serem resolvidos

Também é uma possibilidade. Podemos considerá-la, e acho que pode ser usada em conjunto com a solução inicial pra casos em que a performance é importante.

Gravatar de Klawdyo Klawdyo Resposta publicada em
31/12/2009, 11:01:15

[v0.3] Problemas a serem resolvidos

Pegando a ideia geral aqui do tópico, eu adotei essa prática. Agora a única coisa que eu carrego em Controller::components é o UserAccessComponent pq preciso em todas as páginas.

No geral, eu criei um método load() e o coloquei em AppModel.


	public function load($name){
		if(preg_match("(([A-Za-z]+)Component$)",$name, $out)):
			$s = ClassRegistry::load($out[0], 'Component');
			return $s->initialize($this);
		else:
			return ClassRegistry::load($name);
		endif;
	}

Uma coisa que eu observei, é que o ClassRegistry::load() não inicializa os componentes, ele apenas carrega. Nesse caso, eu forço a chamada ao método initialize() passando como parâmetro o próprio objeto Controller.

Agora quando vou usar um component, só faço


$val = $this->load('ValidationComponent');

E uso os métodos normalmente. Eu acho que está mais produtivo e rápido assim.

Gravatar de Klawdyo Klawdyo Resposta publicada em
31/12/2009, 12:37:12

[v0.3] Problemas a serem resolvidos

Não. Eu coloquei em AppController.
..... 'editar' faz falta.....

Você deve estar logado para responder a um tópico ou adicionar um novo.
Efetue login ou Registre-se para participar das discussões.