Bruno Augusto 417 Denunciar post Postado Março 17, 2011 João, 99.9% de chance de que você não se tornou o programador que é hoje logo que começou a programar, certo? Preciso mesmo lembrar do caos que eram as aplicações antes de haver a separação oferecida pela arquitetura N-tiers, mesmo que o foco do MVC seja mais (ao invés de único, ao meu ver) a View do que as outras duas letras? E, claro, faltou uma opinião sobre o que eu pergunte né? :thumbsup: Compartilhar este post Link para o post Compartilhar em outros sites
William Bruno 1501 Denunciar post Postado Março 17, 2011 Preciso mesmo lembrar do caos que eram as aplicações antes de haver a separação oferecida pela arquitetura N-tiers eu não acho que foi a arquitetura N-Tiers, que veio para 'resolver' esse caos ai Bruno. é possível sim, fazer um código bonito, sem esse conceito, e até sem OO. O problema é que invariavelmente, os programadores de hoje em dia, costumam atribuir as 'melhorias' a apenas uma coisa.(como você acabou de fazer) E isso não é correto. OO veio para resolver uma coisa, e sempre vejo pessoas atribuindo toda a 'evolução' na forma de programar a isso. N-Tiers, Layers vieram para resolver outra, e agora você está achando que elas que 'resolveram tudo' Existem muitas outras coisas antes disso.. e que por falta de conhecimento conceitual, gera esse tipo de opinião. Compartilhar este post Link para o post Compartilhar em outros sites
Bruno Augusto 417 Denunciar post Postado Março 17, 2011 Na na ni na não Não falei que o MVC veio pra resolver TUDO. Talvez tenha sido um comentário levemente influenciado pela decepção que eram os códigos procedurais, verdadeiro aglomerados de pura caca :P A melhoria a que me referi foi única e exclusivamente relativa à esse ponto. Pode ser que por eu ainda estar engatinhando no assunto eu não consiga perceber razão lógica para que a View faça isso que o João propôs e por isso essa divergência de opiniões. Pra quem ainda está estudando o assunto, percebe que MVC server para separar "cada coisa no seu lugar" e, assim como eu, acha estranho esse conceito em que a View faz mais do que apenas exibir os dados. Compartilhar este post Link para o post Compartilhar em outros sites
William Bruno 1501 Denunciar post Postado Março 17, 2011 pela decepção que eram os códigos procedurais, verdadeiro aglomerados de pura caca :P os meus não eram :lol: se os teus eram pura caca, então o problema é seu, e não da metodologia 'procedural'. ainda assim, é possível fazer mais caca ainda, tentando programar em OO, e nem por isso orientação a objetos é uma caca [pense nisso]. Compartilhar este post Link para o post Compartilhar em outros sites
Bruno Augusto 417 Denunciar post Postado Março 17, 2011 Os meus não eram assim um estado da arte, mas não faziam tão feio quanto o sentido proposto pela expressão. Pelo visto, você também não entendeu interamente meu ponto de vista. De repente você entende melhor os padrões do que, de repente você é até melhor programador do que eu, mas não vejo como continuar com essa discussão possa favorecer a fluência do tópico. Já que a lebre foi levantada, vamos ver onde isso dá :thumbsup: Compartilhar este post Link para o post Compartilhar em outros sites
abilhoa 0 Denunciar post Postado Março 17, 2011 Cacete!! Valeu pelo empenho na explicação. :clap: Essa é uma abordagem um pouco diferente dá que estou acostumado. Mas de qualquer forma, o que me intriga é a questão do controller. Veja que, em um contexto global, o seu controller realizará tarefas repetitivas: instanciar e invocar métodos da Model e em seguida carregar a View. Isso pode ser automatizado, pois essas funções não mudam conforme a entidade. Por esse motivo, fico com a impressão que é desnecessário trabalhar com 2 classes pra uma mesma entidade. Mas sei lá, posso estar me atendo a um detalhe sem muita importância. Vamos esquecer os frameworks, o fato de muitos serem famosos não significa que estão corretos. Justamente, por isso é que estou questionando-os. B) Compartilhar este post Link para o post Compartilhar em outros sites
Suissa 1 Denunciar post Postado Março 17, 2011 :clap: :clap: :clap: :clap: :clap: :clap: Como sempre uma ótima explicação! Compartilhar este post Link para o post Compartilhar em outros sites
abilhoa 0 Denunciar post Postado Março 17, 2011 Mas então, pra ser objetivo... Agora vejo que o modelo que propus não está plenamente de acordo com a aboradagem MVC! De qualquer forma, ainda assim é uma solução. Quero saber se esse modelo é ruim? Vocês enxergam alguma vantagem nele ou devo esquecê-lo? É que diversos detalhes nos frameworks atuais não me agradam. Então quero saber se insisto nessa maneira de programar (a que propus) ou se esqueço desses detalhes que me incomadam nos frameworks e desando a trabalhar só com eles (code igniter e cakephp, por exemplo, que são os que já trabalhei). Compartilhar este post Link para o post Compartilhar em outros sites
João Batista Neto 448 Denunciar post Postado Março 17, 2011 Mas então, pra ser objetivo... Agora vejo que o modelo que propus não está plenamente de acordo com a aboradagem MVC! De qualquer forma, ainda assim é uma solução. Quero saber se esse modelo é ruim? Vocês enxergam alguma vantagem nele ou devo esquecê-lo? Não vejo como "bom" ou "ruim". Vejo como MVC ou não MVC, é simples. Antes de voltarmos a falar sobre ActiveRecord, vamos voltar à sua historinha: O usuário entrará na lista de produtos através da url: http://meusite.com.br/produto/listar/ Essa URL chamará o arquivo index.php, que em seguida criará uma instância da classe Controller; A classe Controller irá analisar a URL e irá instanciar o model PRODUTO; Em seguida o controller irá chamar o método LISTAR da classe PRODUTO; Veja só: Com podemos ver, a listagem de produtos envolve alguns casos de uso e, para cada caso de uso, existe uma atividade: Então, de uma forma bem simplista, casos de uso são responsabilidade do Controller: A ação "Listar Produtos" do usuário, feita através da View, será pega pelo Controller que acionará a Model. Quando a Model assumir, ela fará o trabalho dela que é entregar uma listagem de produtos, segundo as regras de negócio; Então, as atividades dos casos de uso, são responsabilidade da Model. Acho que assim fica mais fácil visualizar qual tarefa é responsabilidade de qual participante, então se estivermos tudo bem até aqui, passamos para os outros padrões citados e montamos uma "aplicaçãozinha" com sua história. ;) Compartilhar este post Link para o post Compartilhar em outros sites
Suissa 1 Denunciar post Postado Março 17, 2011 João, 99.9% de chance de que você não se tornou o programador que é hoje logo que começou a programar, certo? Preciso mesmo lembrar do caos que eram as aplicações antes de haver a separação oferecida pela arquitetura N-tiers, mesmo que o foco do MVC seja mais (ao invés de único, ao meu ver) a View do que as outras duas letras? E, claro, faltou uma opinião sobre o que eu pergunte né? :thumbsup: Juro que não entendi isso, MVC o foco é a VIEW? :mellow: Como assim? Compartilhar este post Link para o post Compartilhar em outros sites
abilhoa 0 Denunciar post Postado Março 17, 2011 Então, de uma forma bem simplista, casos de uso são responsabilidade do Controller: A ação "Listar Produtos" do usuário, feita através da View, será pega pelo Controller que acionará a Model. Quando a Model assumir, ela fará o trabalho dela que é entregar uma listagem de produtos, segundo as regras de negócio; Então, as atividades dos casos de uso, são responsabilidade da Model. João, não sei se não estou entendendo seu ponto de vista, mas até agora, grande parte do que você disse, condiz com o que eu demonstrei no exemplo. Veja só o funcionamento desse "framework" hipotético, que segue as minhas idéias: Controller Só existirá um Controller em toda aplicação, pois ela fará automaticamente o controle de tudo. class Controller { private function getModel() { ... rotina para pegar o model da URL ... } private function getAction() { ... rotina para pegar a action da URL } public function controll() { $model = $this->getModel(); $action = $this->getAction(); $view = $action; {$model} = new $model; // cria uma instância do Produto e o torna acessível na View através do objeto $produto; {$model} = $model->{$action}(); // chama o método Listar da model Produto include($view . '.php'); // carrega a view } static public function loadComponent($component) { include($component . '.php'); return new $component; } } Model class Model { ... métodos como save(); find(). findAll(). delete() e outros ... } class Produto extends Model { public function listar() { $this->lista = $this->findAll(); } } View listar.php <? foreach($produto->lista as $p): ?> <li><?=$p->nome?></li> <? endforeach ?> Index.php Finalmente o objeto que fará a aplicação toda rodar. $controller = new Controller; $controller->control(); // controla toda a aplicação Observe que a entidade Produto não terá um controlador só pra ela, pois há um controlador geral. O meu problema mora na seguinte situação: Se eu precisar de um componente de validação, terei de fazê-lo na Model (já que é onde a regra de negócio deve estar). Mas como instanciar um Component na Model sem passar pelo Controller? Por esse motivo, criei o método estático. class Produto extends Model { public function save() { $validation = Controller::loadComponent("Validação"); ... } } Resta saber se essa chamada estática fere o padrão MVC, como o colega William Bruno mencionou. De qualquer forma, pode continuar com suas explicações, pois está muito interessante. Compartilhar este post Link para o post Compartilhar em outros sites
João Batista Neto 448 Denunciar post Postado Março 17, 2011 Resta saber se essa chamada estática fere o padrão MVC, como o colega William Bruno mencionou. Não é responsabilidade do Controller carregar esse tipo de coisa. Se você quiser um participante para fazer a resolução e carregamento de pacotes, helpers, recursos, etc., crie um ClassLoader, Essa responsabilidade está fora do escopo das atribuições do Controller. Tanto o Controller quanto a Model ou a View podem sem problemas utilizar um ClassLoader, mas uma camada chamar outra (que não deveria) para carregar uma coisa (que não é atribuição) de outro participante, é errado. Existem vários padrões de criação que você pode utilizar para isso, eu já exemplifiquei alguns em outros tópicos, dê uma olhada no tópico índice :seta: http://forum.imasters.com.br/topic/402329-padroes-gof/ Compartilhar este post Link para o post Compartilhar em outros sites
abilhoa 0 Denunciar post Postado Março 17, 2011 Se você quiser um participante para fazer a resolução e carregamento de pacotes, helpers, recursos, etc., crie um ClassLoader, Essa responsabilidade está fora do escopo das atribuições do Controller. Tanto o Controller quanto a Model ou a View podem sem problemas utilizar um ClassLoader, mas uma camada chamar outra (que não deveria) para carregar uma coisa (que não é atribuição) de outro participante, é errado. Estou entendo, mas dessa forma parece que meu modelo está fadado ao fracasso. Veja a seguinte situação: class Controller { ... static public function loadTemplate($template) { $this->template = $template; } static public function loadComponent($component) { include($component . '.php'); $this->{$model} = new $component; } public function controll() { $model = $this->getModel(); $action = $this->getAction(); $view = $action; {$model} = new $model; // cria uma instância do Produto e o torna acessível na View através do objeto $produto; {$model} = $model->{$action}(); // chama o método Listar da model Produto include($this->template); include($view . '.php'); // carrega a view } } class Produto extends Model { public function __construct() { Controller::loadTemplate("Template.php"); } public function save() { Controller::loadComponent("Validation"); $validation->validate(); ... } } Eu não "poderia" criar uma classe Loader, pois dessa forma eu não conseguiria disponibilizar automaticamente ao Model, o objeto do Component. Pode parecer bobeira, mas há outras implicações nisso também. E no caso de carregar um determinado template, também não poderia fazer sem acessar o Controller. Compartilhar este post Link para o post Compartilhar em outros sites
João Batista Neto 448 Denunciar post Postado Março 18, 2011 static public function loadTemplate($template) { $this->template = $template; } Você tem um erro sério ai, métodos estáticos são métodos de classe. Não existe um objeto ai para você utilizar $this. Teste seu código com E_STRICT static public function loadComponent($component) { include($component . '.php'); $this->{$model} = new $component; } crystal_ball_mode=On Tome muito cuidado com isso, é o tipo de código que tende a dar problemas sérios e, sempre, muito difíceis de se depurar e corrigir. Sem contar que se alguém for manter esse código, sequer conseguirá lê-lo. Eu não "poderia" criar uma classe Loader, pois dessa forma eu não conseguiria disponibilizar automaticamente ao Model, o objeto do Component. Pode parecer bobeira, mas há outras implicações nisso também. E no caso de carregar um determinado template, também não poderia fazer sem acessar o Controller. Fiquei curioso agora, O que significa "outras implicações" ? Veja amigo, estou realmente disposto a tentar lhe ajudar, mas não sonegue informações. Se existe um contexto por trás dessa situação, descreva aqui, toda sua situação. E se eu estiver indo muito rápido, muito devagar ou se os exemplos e ilustrações estiverem muito complexas, diga também que tento melhorá-las. Mas não deixe de dar todas as informações que você tiver. ;) Compartilhar este post Link para o post Compartilhar em outros sites
abilhoa 0 Denunciar post Postado Março 18, 2011 Você tem um erro sério ai, métodos estáticos são métodos de classe. Não existe um objeto ai para você utilizar $this. Teste seu código com E_STRICT É, eu me afobei na resposta e acabei comentendo esses erros, mas quando eu tentei editá-lo o tópico todo perdeu a identação. Tudo virou uma única linha no editor e eu acabei desistindo hehe. Mas vamos lá, vou postar o código correto do exemplo agora: // CONTROLLER class Controller { static $model; static $template; static public function loadTemplate($template) { self::$template = $template; } static public function loadComponent($component) { self::$component = $component; } public function control() { $model = $this->getModel(); // digamos que esta linha pegue a Model da URL $action = $this->getAction(); // e essa a Action $view = $action; // a View terá o mesmo nome da Action include($model . '.php'); {$model} = new $model; // cria uma instância do Produto e o torna acessível na View através do objeto $produto; {$model} = $model->{$action}(); // chama o método Listar da model Produto $component = self::$component; // só pra facilitar o entendimento do código include($component . '.php'); {$model}->{$component} = new $component; include(self::$template); include($view . '.php'); } } // MODEL class Produto extends Model { public function __construct() { Controller::loadTemplate("Template.php"); } public function save() { Controller::loadComponent("Validation"); $this->validation->set("nome", "required"); if($this->validation->validate()) ... } } Tome muito cuidado com isso, é o tipo de código que tende a dar problemas sérios e, sempre, muito difíceis de se depurar e corrigir. Sem contar que se alguém for manter esse código, sequer conseguirá lê-lo. Porque você diz isso? Agora que eu arrumei os erros, você ainda acha isso? Fiquei curioso agora, O que significa "outras implicações" ? Veja amigo, estou realmente disposto a tentar lhe ajudar, mas não sonegue informações. Se existe um contexto por trás dessa situação, descreva aqui, toda sua situação. E se eu estiver indo muito rápido, muito devagar ou se os exemplos e ilustrações estiverem muito complexas, diga também que tento melhorá-las. Mas não deixe de dar todas as informações que você tiver. ;) Desculpe se fui vago, mas é que achei que você já devia estar de saco cheio dessa ladainha :yay: Vou tentar explicar resumidamente como funciona o cerne do meu "framework". O controller lê a URL e interpreta as váriáveis passadas: /model/action/parametros; Então a model é carregada (através do construtor, alguns recursos já podem ser carregados: component, helpers, templates); Aí a action da Model é invocada (alguns recursos podem ser carregados: component, helpers, templates); Em seguida, um Template é carregado (include); E por fim, a view é carregada (include) Meus problemas são os seguintes: Como carregar um template, dentro da Model sem invocar o Controller, uma vez que toda minha lógica de "renderização" está lá? Como fornecer uma instância dentro da Model, dos recursos carregados: component e helper; Através de uma classe Loader eu teria de fazer: $this->loader = new Loader; $this->validation = $this->loader->load("Validation"); ao invés de apenas Controller::loadComponent("Validation"); Tenho um sistema de erro no controller, que lê toda a aplicação, verifica os erros e só então renderiza a camada de visão. Caso hajam erros (inclusive nas views), são exibidas telas amigáveis de ajuda. É por aí, mas você já me deu algumas idéias que talvez resolvam esses problemas, mas primeiro quero ver a sua opinião. Compartilhar este post Link para o post Compartilhar em outros sites
abilhoa 0 Denunciar post Postado Março 26, 2011 João, analisando seu outro tópico (http://forum.imaster...de-uso-e-teste/) deu pra ver que, unido às dicas deste, dá pra fazer um esquema bem legal. No entando, minha dúvida básica permanece. Ou não estou conseguindo me expressar ou não estou entendendo as respostas corretamente. Mas vamos lá: O que realmente está me incomodando é o papel das classes Controllers (não a camada em si). Essas classes tem a responsabilidade de receber as requisições do usuário e direcioná-las à Model e View corretos. Mas eu não vejo o porque de não automatizar essa função, para evitar a repetição de código. Queria eleminar a necessidade de se criar uma classe Controller pra cada funcionalidade. No meu exemplo a seguir, a classe RequestMapper seria responsável por analisar as requisições do usuário e carregar as classes necessárias. Mas ela seria única para toda a aplicação. Seria incluída na index.php e nunca mais seria instânciada novamente. Nada de um ProdutoRequestMapper, ou CategoriaRequestMapper. (Obs: a classe RequestMapper é a que eu estava chamando de Controller nos posts anteriores, mas acredito que isso estivesse causando confusão, por isso mudei o nome). class RequestMapper { public function mapper(){ $model = $_GET['model']; $action = $_GET['action']; ${$model} = new $model; // cria uma instância da Model com o mesmo nome; ${$model}->{$action}(); // chama o método da Model requisitado pela Action $view = $action; include($view); // carrega a View com o mesmo nome da Action } } $RequestMapper = new RequestMapper; $RequestMapper->mapper(); Então, a única parte que precisários trabalhar para tratar as funcionalidades da aplicação seria a Model (além da view, é claro). class Produto extends Model{ public function listar(){ $this->produtos = $this->find('all'); } } class Categoria extends Model{ public function listar(){ $this->categorias = $this->find('all'); } } Aí, através da URL www.meusite.com/?model=Produto&action=Listar a classe RequestMapper iria chamar a model Produto e executar o método Listar. Logo em seguida a view Listar.php seria incluída e a instância da classe Produto estaria automaticamente disponível para a View. O mesmo ocorreria para a classe Categoria, caso a URL fosse www.meusite.com/?model=Categoria&action=Listar Então... isso pode ser chamado de MVC, sendo que a camada C está apenas encapsulada? a classe RequestMapper pode ser considerada um Controller genérico ou, quem sabe, um FrontController, mas que invoca Models ao invés de Controllers? essa arquitetura está correta, errada, é imprópria pra menores...? Depois que essas dúvidas forem sanadas, tenho outras relacionadas. Compartilhar este post Link para o post Compartilhar em outros sites