Perguntas sobre MVC Desktop! Existe solução? (+ MVP,MVC WEB,Observer e Exception's)

Oi fantomas! Nossa cara não sabe como estou feliz de ouvir isso de você! :smiley: :smiley: :smiley: Muito bom!

Poxa que legal a ideia cara! Eu vou estudar direitinho o exception para não postar qualquer coisa aqui de qualquer jeito e assim que conseguir implementá-lo eu volto e mostro como ficou, ok? Não vou sumir e deixar o tópico inacabado.
Também entendi a respeito dos campos… com certeza dou razão no caso de poucos campos é exagero mesmo dividir tanto. Mas para exemplo acho que ficou legal (acredito que você também ache), ainda mais que é um exemplo de cadastro. Mas foi bom notificar isso, até mesmo para os demais usuários iniciantes (como eu) do GUJ ficarem atentos!

Poxa não tenho nem palavras para agradecer pela atenção que está disponibilizando do seu tempo em ajudar. Muito legal mesmo! :smiley:
Sucesso rapaz, tú merece! [color=red]Obrigadão![/color] Até mais. :wink:

Oi fantomas! Como prometido, voltei! :smiley:

[quote=pedromuyala][quote=fantomas]
No exemplo que vc passou (o último) vc poderia utilizar exceptions para deixar a mensagem dentro da view. Por exemplo, de dentro da view ao clicar no botão confirmar vc executa o código que faz atualização no “controller” e este código por sua vez retorna uma resposta positiva ou negativa atravez de uma exception. Assim vc consegue deixar detalhes que são relacionados a “view”, dentro da view.
[/quote]
Poxa que legal a ideia cara! Eu vou estudar direitinho o exception para não postar qualquer coisa aqui de qualquer jeito e assim que conseguir implementá-lo eu volto e mostro como ficou, ok? Não vou sumir e deixar o tópico inacabado.
[/quote]

Então passei esses últimos quatro dias tentando implementar Exception no código mas infelizmente não consegui. :oops:
Não sei se estou fazendo certo (alias acho que estou fazendo uma bela asneira), até porque nunca trabalhei com exception. Mas não consigo implementar no código do controle, como havia escrito na citação… dá erro na compilação :frowning:

Veja só as mudanças…

na Visão:

class ClienteView extends JPanel {

   private JButton botaoCadastrar;
   private JTextField nome;
   private JTextField cpf;
   private JLabel lblcad; // JLABEL PARA NOTIFICAR ERRO NO CADASTRO.

   ClienteView() {
      nome = new JTextField(10);
      add(nome);
      cpf = new JTextField(10);
      add(cpf);
      botaoCadastrar = new JButton("Cadastrar");
      add(botaoCadastrar);
      lblcad = new JLabel(); // CRIADO JLABEL PARA NOTIFICAR ERRO!
      add(lblcad); // ADICIONADO AO PAINEL.
   }
   
   public void cadastrar(ActionListener event) { // ALTERAÇÃO DO MÉTODO PARA RECEBER EXCEÇÃO!
      try {
         botaoCadastrar.addActionListener(event);
      }
      catch (Exception e) {
         lblcad.setText("Cliente cadastrado com sucesso!");
   }

   String getCPF() {
      return cpf.getText();
   }
			
    void setCPF(String text) {
      cpf.setText(text);
   }

   String getNome() {
      return nome.getText();
   }
			
    void setNome(String text) {
      nome.setText(text);
   }
}

e no Controle:

public class ClienteControl {
    
   private Cliente cli;
   private ClienteView cv;

    ClienteControl(Cliente cli, ClienteView cv) {
      this.cli = cli;
      this.cv = cv;
      cv.cadastrar(new CadastrarCliente());
   }

   class CadastrarCliente implements ActionListener { // MÉTODO ALTERADO PARA CRIAR EXCEÇÃO!
      public void actionPerformed(ActionEvent event) throws Exception { // Linha do problema!
         try {
            cli.setCPF(cv.getCPF());
            cli.setNome(cv.getNome());
            throw new Exception();
         }
         catch(Exception e) {
            throw e;
         }
      }
   }
}

No Main nada no código foi alterado mantendo igual!

Mas o problema que ocorre no compilador é o seguinte: ClienteControl.java:13: actionPerformed(java.awt.event.ActionEvent) in ClienteControl.CadastrarCliente cannot implement actionPerformed(java.awt.event.ActionEvent) in java.awt.event.ActionListener; overridden method does not throw java.lang.Exception

Estou fazendo besteira ou será que existe outra forma de fazer a exception para que possa funcionar corretamente?
Tentei várias maneiras diferentes que fui olhando na net mas não estou conseguindo enxergar o erro (como disse, nunca trabalhei com exceptions!).
[color=blue]Obrigado fantomas e todos que estão ajudando![/color] :smiley:

Estou no aguardo por novas respostas! :smiley:

Nada mesmo pessoal? Está muito ruim assim? :shock: :oops:

Vc poderia fazer assim:

[code]class ClienteView extends JPanel {

private JButton botaoCadastrar;
private JTextField nome;
private JTextField cpf;
private JLabel lblcad; // JLABEL PARA NOTIFICAR ERRO NO CADASTRO.

ClienteView() {
nome = new JTextField(10);
add(nome);
cpf = new JTextField(10);
add(cpf);
botaoCadastrar = new JButton(“Cadastrar”);
add(botaoCadastrar);
lblcad = new JLabel(); // CRIADO JLABEL PARA NOTIFICAR ERRO!
add(lblcad); // ADICIONADO AO PAINEL.
}

public void cadastrar(ActionListener event) { // Alterei aqui!
botaoCadastrar.addActionListener(event);
}

String getCPF() {
return cpf.getText();
}

void setCPF(String text) {
  cpf.setText(text);

}

String getNome() {
return nome.getText();
}

void setNome(String text) {
  nome.setText(text);

}

void displayMsgSucesso() { // Alterei aqui!
lblcad.setText(“Cliente cadastrado com sucesso!”);
}

void displayMsgErro() { // Alterei aqui!
lblcad.setText(“Erro ao cadastrar o cliente!”);
}
}[/code]

public class ClienteControl {
    
   private Cliente cli;
   private ClienteView cv;

    ClienteControl(Cliente cli, ClienteView cv) {
      this.cli = cli;
      this.cv = cv;
      cv.cadastrar(new CadastrarCliente());
   }

  class CadastrarCliente implements ActionListener { 
      public void actionPerformed(ActionEvent event) { // Alterei aqui, este método não espera uma exception.
         try {
            cli.setCPF(cv.getCPF());
            cli.setNome(cv.getNome());

            cv.displayMsgSucesso(); // Alterei aqui

         } catch(Exception e) {

	    cv.displayMsgErro();  // Alterei aqui

            e.printStackTrace();
         }
      }
   }
}

flws

Olá fantomas, boa noite! Desculpa não responder durante a tarde. :smiley:
Muito legal a idéia de deixar a visão já com os métodos de sucesso/insucesso que são acionados pelo controle através de Exception’s.

Sim! Neste seu caso o forte acoplamento existe, porque na verdade o que vc fêz foi uma separação de código, uma parte vc chamou de model, outra de view e outra de controller; isto é uma implementação completa do padrão MVC? Eu diria que não por causa de coisas como esta que vc falou, o acoplamento. Mas por que ficou interessante? Porque você deixou o código mais organizado, mais fácil de executar manutenções e introduziu uma estratégia de construir seus códigos o que deixa bem mais fácil de entender o sistema.
[/quote]

Uma simples pergunta: Como dito, frameworks MVC ajudam e muito a minimizar o forte acoplamento. Isso significa que esse último código postado (o que faz uso correto do Exception) ainda pode ser “melhor desacoplado” ou ele já está, no mínimo, satisfatório. Se existe ainda formas de desacoplar (ou seja, torná-lo um MVC real), pode me dar uma dica para que estude o caso :?:

Como havia escrito no primeiro post com código-exemplo, ainda tenho algumas dúvidas mas para não “tumultuar” o tópico com perguntas, assim que se esclarece uma posto a outra. E a pergunta de hoje já é uma dúvida que tenho desde que começei a estudar MVC, que é sobre a validação de dados!
Tentei hoje implementar o que eu consegui entender sobre “validação no modelo do MVC”. Para isso, faço validação do CPF informado. Veja nos códigos abaixo:
[color=orange]* Limpei os comentários antigos, para ficar só os novos! :wink:[/color]
Visão

class ClienteView extends JPanel {

   private JButton botaoCadastrar;
   private JTextField nome;
   private JTextField cpf;
   private JLabel lblcad;

   ClienteView() {
      nome = new JTextField(10);
      add(nome);
      cpf = new JTextField(10);
      add(cpf);
      botaoCadastrar = new JButton("Cadastrar");
      add(botaoCadastrar);
      lblcad = new JLabel();
      add(lblcad);
   }
   
   public void cadastrar(ActionListener event) {
       botaoCadastrar.addActionListener(event);
   }

   String getCPF() {
      return cpf.getText();
   }
			
    void setCPF(String text) {
      cpf.setText(text);
   }

   String getNome() {
      return nome.getText();
   }
			
    void setNome(String text) {
      nome.setText(text);
   }

   void displayMsgSucesso() {
         lblcad.setText("Cliente cadastrado com sucesso!");
   }

   void displayMsgErro() {
         lblcad.setText("Erro ao cadastrar o cliente!");
   }

   /* Método para exibição do resultado da validação! */
   void displayCPFErro() {
         lblcad.setText("Erro no CPF do cliente!");
   }
   /* Fim da exibição */

}

Controle:

public class ClienteControl {
    
   private Cliente cli;
   private ClienteView cv;

    ClienteControl(Cliente cli, ClienteView cv) {
      this.cli = cli;
      this.cv = cv;
      cv.cadastrar(new CadastrarCliente());
   }

  class CadastrarCliente implements ActionListener { 
      public void actionPerformed(ActionEvent event) {
         try {
            cli.setCPF(cv.getCPF());
            
            /* Código de validação do CPF no CONTROLE! */
            if (!Util.validaCPF(cv.getCPF())) { // Util é uma class abstrata e valida o CPF ("true" se validar ou "false" se invalidar).
               cv.displayCPFErro();
               cli.setCPF(null);
            }
            /* Fim da validação */
            else {
               cli.setNome(cv.getNome());
               cv.displayMsgSucesso();
            }
         } 
         catch(Exception e) {
            cv.displayMsgErro();
            e.printStackTrace();
         }
      }
   }
}

Minha pergunta então é: Está visivelmente correto a forma como ficou implementada a validação do CPF? Sempre vou ter que criar métodos com mensagens já prontas na visão para cada situação?
E se eu tiver mais campos para validar, como RG, CEP? Não existe uma forma para que no momento da validação caso ela retorne inválida (false) o try seja interrompido de forma que não chame o método displayMsgSucesso()? Acredito eu que seja gerando uma exceção… mas onde? Na Util? Ou no próprio controle?

Só uma obs: Entende porque perguntei logo no começo sobre o acoplamento? Eu vejo que cada vez mais que o sisteminha vai aumentando o controle vai se acoplando mais à visão. Ou será um engano meu. Que parece dar essa sensação de acoplamento, parece.

Fantomas, rapaz eu estou me sentindo já envergonhado :oops: com a atenção que tem dado ao tópico. Já já você vira as 1000 mensagens no GUJ, está de parabéns. Tenho certeza que muita gente você já ajudou e continua ajudando. Espero com toda certeza ainda um dia saber que se tornou, por exemplo, um moderador do fórum. :smiley:
Você merece e vai ser com enorme alegria que vou receber essa notícia o dia que se tornar um moderador. [color=red]Obrigado fantomas![/color] :wink:

Ninguém arrisca uma opinião? :frowning: Nem do código nem do acoplamento… :cry:

Oi Pedro,

Não li todos os seus posts, mas no caso da classe utilitaria eu faria o seguinte:

o método da classe Util que valida o CPF relança uma excesão e não gera log

a camada que chamou recupera a excessão e faz o log

algo parecido

[code]class Util {

Boolean validaCPF(String cpf) throws ValidationCPFException {

 try {
  //valida
 } catch(Exceptions.... e) {
   // aqui eu handle - trato - todas as excessões possiveis
   throw new ValidationCPFException(VALIDATION_CPF, e.getStackTrace());
 }

}

class Utiliza {

void metodoValida(String cpf) {

try {
  Util.validaCPF(cpf);
} catch (ValidationCPFException v) {
  log.error('erro validando"+e....); 
  // posso deixar correr o erro ou então tentar recuperar o que aconteceu..
}

}
}[/code]

resumindo, na minha opinião classes utilitárias não devem ser reponsáveis por saber o que fazer quando uma excessão ocorre, elas apenas retornam, pode até retornar um null ou 0, um valor default… etc
na camada de business, ou outra que utilize a classe, eu só tenho uma excessão do tipo ValidaCPFException… fica mais facil tratar assim…

[color=blue]Olá André, boa noite![/color] Obrigado por iniciar sua participação aqui no tópico. :smiley:
Sim legal a idéia, entendi certinho. Para deixar ainda melhor implementei no controle sua ideia para dar continuidade ao código-exemplo. Veja como ficou:

Na Visão, nada mudou.

No Controle:

public class ClienteControl {
    
   private Cliente cli;
   private ClienteView cv;
   
   ClienteControl(Cliente cli, ClienteView cv) {
      this.cli = cli;
      this.cv = cv;
      cv.cadastrar(new CadastrarCliente());
   }
   
   class CadastrarCliente implements ActionListener { 
      public void actionPerformed(ActionEvent event) {
         try {

         /* NOVO Código de validação do CPF no CONTROLE! */
            Util.validaCPF(cv.getCPF());
            cli.setCPF(cv.getCPF());
         /* FIM do Código de validação do CPF! */

            cli.setNome(cv.getNome());
            cv.displayMsgSucesso();
         }
         catch (Exception e) {
            cv.displayMsgErro();
            e.printStackTrace();
         }

         /* NOVO Código de validação do CPF no CONTROLE! */
         catch (ValidationCPFException v) {
            cv.displayCPFErro();
         }
         /* FIM do Código de validação do CPF! */

      }
   }
}

No meu entender ficou legal! :smiley:

:?: Três perguntas ainda estão em aberto:

Em seguida vou postar a próxima pergunta! Enquanto isso se alguém quiser arriscar responder a citada… agradeço. [color=red]Obrigado![/color] :wink:

Estou fazendo perguntas sem respostas né? :cry:
Acho que estou perguntando “besteiras”. :frowning:

  1. Sempre vou ter que criar métodos com mensagens já prontas na visão para cada situação?
    Não!
    Você pode mudar um pouco esta abortagem fazendo o seguinte:

[code]public class View {
private Controller controller = null;
private JButton btnExecute = new JButton(“Executar”);

public View(Controller controller) {
this.controller = controller;
this.initialize();
}

private void initialize() {
      btnExecute.addActionListener(new ActionListener() {
           View.this.executar();
      });
}

private void executar() {
    try {
         this.controller.executar();
          WindowUtil.showMessage("Sucesso ao executar!");
    } catch( Exception e ) {
         WindowUtil.showMessage("Erro ao executar!");
         e.printStackTrace();
    }
}

}[/code]

  1. Uma simples pergunta: Como dito, frameworks MVC ajudam e muito a minimizar o forte acoplamento. Isso significa que esse último código postado (o que faz uso correto do Exception) ainda pode ser “melhor desacoplado” ou ele já está, no mínimo, satisfatório. Se existe ainda formas de desacoplar (ou seja, torná-lo um MVC real), pode me dar uma dica para que estude o caso?

Tem esse framework aqui: http://www.javaworld.com/javaworld/jw-06-2005/jw-0620-tikeswing.html.
Tem tambem o genesis (brasileiro): https://genesis.dev.java.net/nonav/3.2/maven-site/pt-BR/index.html, o objetivo principal deste não é implementar o padrão MVC, mas ajuda bastante quem está querendo fazer isto.

Não deixe de ler este conteúdo também: http://java.sun.com/developer/technicalArticles/javase/mvc/

  1. Só uma obs: Entende porque perguntei logo no começo sobre o acoplamento? Eu vejo que cada vez mais que o sisteminha vai aumentando e o controle vai se acoplando mais à visão. Ou será um engano meu? Que parece dar essa sensação de acoplamento, parece.

Reduzir acoplamento nem sempre é simples e pode causar esta impressão mesmo. Mas dá para vc testar o nível de acoplamento de uma forma até simples na minha opinião. Basta vc observar o seu código e fazer as seguintes perguntas para vc mesmo:

  1. Eu consigo utilizar este controller em uma outra situação (em um sistema web por exemplo) sem modificar nada?
  2. Eu consigo utilizar esta view com um controller que possua comportamentos diferentes?
  3. Eu consigo utilizar este model em uma situação bem diferente desta?

Sim for sim para todas estas perguntas significa que vc está no caminho certo.

Lembrando que interfaces são o caminho para um bom desacoplamento, independente de qualquer situação ou padrão; portanto faça uma revisão.

flws

Boa noite fantomas, obrigado mais uma vez em estar acompanhando o tópico. :smiley:
Legal a última idéia. Dessa forma percebo um desacoplamento geral do controle com a visão e vice-versa, até porque b[/b] o método executar() poderia ter parametros que levariam os dados da visão ao controle. Estou certo? E um detalhe que está fazendo uma enorme diferença é o uso de exceções. Nunca imaginei a importancia das exceções em códigos JAVA.

Vou aproveitar o embalo e colocar mais uma pergunta:b[/b] E se eu precisar informar o usuário na visão do tipo de exceção que ocorreu ao executar o controle nessa nova abordagem apresentada?
Ex: Data inválida -> “Erro: Informe corretamente a data de nascimento!” ou Ex2: “Erro: CPF inválido”. Como o usuário vai saber que só “tal” campo está com problema?
Acredito eu que será com o uso e tratamento de Exceptions, ou não? :shock:

Vou aguardar pela resposta para implementar essa nova abordagem (desacoplamento) no código-exemplo que vinha sendo mostrado. Vou aproveitar também e incluir novos atributos para ficar melhor perceptível a solução. :wink:

[color=green][size=16]Muito obrigado galera do GUJ![/size][/color] :thumbup: Aguardo pela resposta, opinião, sugestão, crítica…
fantomas obrigado cara por estar praticamente diariamente respondendo neste tópico e como você diz: flws

Certo.

[quote=pedromuyala]
Vou aproveitar o embalo e colocar mais uma pergunta:(2) E se eu precisar informar o usuário na visão do tipo de exceção que ocorreu ao executar o controle nessa nova abordagem apresentada?
Ex: Data inválida -> “Erro: Informe corretamente a data de nascimento!” ou Ex2: “Erro: CPF inválido”. Como o usuário vai saber que só “tal” campo está com problema?
Acredito eu que será com o uso e tratamento de Exceptions, ou não?[/quote]

Em alguns casos vc consegue retornar resultados sem utilizar exceptions retornando apenas um código ou um valor true ou false; algumas abordagens sugerem vc criar exceptions customizadas quando vc está em um contexto mais complexo como os encontrados em sistemas web, que é bacana também. Quando vc executa uma validação em um controller sem envolver mais nada é mais tranquilo, mas quando a validação ocorre em um servidor muitas podem acontecer, a validação pode retornar positiva, negativa ou pode ocorrer um problema de acesso a base de dados ou até na rede; nestes casos a estratégia de utilizar exceptions pode começar a ficar interessante.

Aqui no forum existem algumas discuções sobre este tema, vê se consegue encontrar.

Lidar com exceptions requer boas práticas, portanto é bom fazer uma pesquisa sobre o assunto; tem bastante na net, eis aqui um link bacaninha: http://onjava.com/pub/a/onjava/2003/11/19/exceptions.html não deixe de lêr e entender.

[]

Olá fantomas, obrigado por continuar acompanhando o tópico! :wink:
Maravilha! Vou entender direitinho as exceções antes de fazer as modificações no código.
Uma dica também para quem está atrás de aprender exceções é a revista MundoJava nº36.
Assim que estiver ciente das exceções, volto a postar o código para mostrar como ficou já implementando a nova abordagem sugerida (desacoplamento)!
[color=red]OBRIGADO A TODOS![/color] Não deixem de opinar, criticar…

Olá pessoal do GUJ! :smiley:
Como prometido, passei esses últimos três dias estudando Exception para tentar chegar a melhor solução cabível no código-exemplo que estamos criando.
Tentei ao máximo possível seguir os conselhos do fantomas e André Fonseca para implementar as Exception. Importante também o artigo deste mês da revista MundoJava no aprendizado. :thumbup:

Vamos ao código-exemplo, que sofreu muita mudança dos últimos exemplos postados, aplicando a nova abordagem (desacoplamento entre visão <-> controle) e o uso de Exception’s.

CLASSES PARA TRATAR EXCEÇÃO:

Superclasse:

public class CadastraException extends Exception {
   
   private String msg;
   
   public CadastraException(String msg) {
      super(msg);
      this.msg = msg;
   }

   public String getMessage() {
      return msg;
   }
}

Subclasse:

public class CPFException extends CadastraException {
   
   public CPFException() {
      super("CPF Inválido");
   }
}

CLASSES DO MVC:

No BEAN CLIENTE (modelo), nada mudou.

Controle:

public class ClienteControl {   
       
   private Cliente cli = null;   
   
   ClienteControl(Cliente cli) {   
      this.cli = cli;   
   }
   
   public void executar(String nome, String cpf) throws Exception {
      try {
         if(!Util.validaCPF(cpf))
            throw new CPFException();
         cli.setCPF(cpf);
         cli.setNome(nome);
      }
         catch(Exception e) {
            throw e;
         }
   }    
}    

*OBS: Util.validaCPF(cpf) retorna valor booleano!

Visão:

public class ClienteView extends JPanel {
	 
   private ClienteControl controller = null;
   private JButton btnCadastrar;
   private JTextField nome;   
   private JTextField cpf;   
   private JLabel lblCad; 
 
   public ClienteView(ClienteControl controller) {
      this.controller = controller;
      this.initialize();
   }
   
   private void initialize() {
      nome = new JTextField(10);   
      add(nome);   
      cpf = new JTextField(10);   
      add(cpf);   
      btnCadastrar = new JButton("Cadastrar");   
      btnCadastrar.addActionListener(
             new ActionListener() {
                public void actionPerformed(ActionEvent e) {		     
                  ClienteView.this.executar();
               }
            });
      add(btnCadastrar);   
      lblCad = new JLabel();   
      add(lblCad);   
   }
   
   private void executar() {
      try {
         this.controller.executar(nome.getText(), cpf.getText());
         lblCad.setText("Cadastro realizado com sucesso");
      }
          catch (CadastraException e) {
            lblCad.setText(e.getMessage());
         }
          catch (Exception e) {
            lblCad.setText("Problemas ao cadastrar. Tente novamente!");
         }
   }  
}

main:

public class Cadastro extends JFrame{
   
   Cadastro() {
      Cliente cli = new Cliente(); 
      ClienteControl con = new ClienteControl(cli);
      ClienteView cv = new ClienteView(con);
      add(cv);
      setVisible(true);
   }

    public static void main (String args[]) {
      Cadastro cadastrar = new Cadastro();
   }
}

Reparem que a visão finalmente está (na minha humilde opinião de aprendiz) muito bem desacoplada do controle. O código do controle está mais legível também. :smiley:

Bem, a minha primeira dúvida com esse novo código é a seguinte: b A hierarquia das classes que compõe as Exception está correta?[/b] (Veja a imagem em anexo!)

Repare que criei uma superclasse CadastraException que é herdada pelas subclasses necessárias para avisar sobre exceções de validações que possam ocorrer durante o cadastro do cliente. Também não descartei a opção de tratar demais exceções que possam ocorrer, como conexão com BD, rede, etc… Repare na visão que se a exceção for de validação ela diz onde ocorreu o erro (qual dado de qual campo gerou uma Exception) e se a exceção for de outro tipo (não conhecido até este momento) só informa com uma mensagem que “ocorreu um problema se possível tente novamente”! (Veja o método [color=blue]executar() na linha 31[/color] do ClienteView). Na imagem exemplo coloquei até uma classe CEPException e OutraException para mostrar a hierarquia. Está correto o procedimento?
O que mais preocupa-me nessa situação é que a mensagem da exceção está sendo tratada fora da visão, o que vai contra o que o fantomas me ensinou em uma postagem anterior quando explicou “que é para deixar detalhes da View dentro da View”. :shock:

A minha segunda dúvida é a seguinte: b A Util.validaCPF(cpf) retorna um valor booleano para o controle que caso seja “false” lança uma CPFException (cria e lança no controle). Eu poderia fazer a Util.validaCPF(cpf) criar e lançar a CPFException() ao invés de retornar um boolean?[/b] Ou seja, aquilo que o André Fonseca propos em uma postagem anterior. (Veja linhas [color=blue]11 e 12[/color] do ClienteControl!)

[color=red]Pessoal[/color], VALE PARA TODOS, não deixem de opinar. Sua opinião/sugestão/crítica é muito importante para manter o tópico vivo e contribuir com todos os companheiros do GUJ! :wink:
Se você acredita que algo deve mudar no código-exemplo também não deixe de postar. :idea: E não deixe de selecionar a opção para acompanhar o tópico. Talvés nesse momento não possa ajudar, mas pode surgir uma dúvida que você poderá contribuir!

[size=16][color=green]OBRIGADO GUJ[/color] por proporcionar essa comunidade linda![/size] :arrow: O Brasil inteiro ganha com isso!

Fico no aguardo por novas respostas. Assim que estiver com essas questões solucionadas lançarei nova pergunta para não embolar muitas perguntas com muitas respostas e acabar ficando uma coisa sem começo nem fim, sem lógica entre pergunta e resposta!
Um abraço especial aí para o fantomas, futuro moderador do GUJ, :lol: ele merece!

Eu preferiria estender de RuntimeException, para evitar a lixarada de throws que as checked exceptions precisam.

Outra coisa é que você não está seguindo o princiípio de atirar a exception mais específica, de fora do teu método vai parecer que é tudo Exception. Remova os “throws Exception”

Sobre a segunda pergunta, se quiser que o teu método de checagem também atire uma exception, crie um método tipo validaCPFComException, e deixe o validaCPF em paz. Pelo menos vai ter as duas opções, não se obrigando a fazer ou de um jeito ou de outro.

Olá Bruno Laturner, obrigado por iniciar sua participação no tópico! :wink:

[quote=Bruno Laturner]Eu preferiria estender de RuntimeException, para evitar a lixarada de throws que as checked exceptions precisam.

Outra coisa é que você não está seguindo o princiípio de atirar a exception mais específica, de fora do teu método vai parecer que é tudo Exception. Remova os “throws Exception”[/quote]

Mas e no caso de ocorrer uma exceção, por exemplo, ao conectar-se ao BD, na rede ou uma outra que não conheço?
Se eu remover “throws Exception” do controle (pelo que estou entendendo) teria que substituir por “throws CadastraException”.
Aí como ficariam as exceções que não estendem CadastraException?

Opinem, não deixem de opinar! Fico no aguardo pela resposta! :smiley:
[color=red]OBRIGADO![/color]

Viraria um throws CadastraException, SQLException, IOException, ParseException, ClassNotFoundException, IllegalAccessException, e outras exceptions…

Vai atirando até vc perceber que a tua classe virou um Mega Zord, e que você está dando responsabilidades demais para ela.

Há um tempo atrás teve uma discussão no arquitetura de sistemas que também conversamos sobre isso. Uma maneira de evitar é saber que as camadas que chamaram o teu código não querem saber o que você está usando, nem as exceções que essas APIs atiram. Converta as exceções de camadas mais abaixo para exceções da sua camada, isso quando forem exceções que você não pode tratar e continuar com a tua vida.

Dito isso, continue a atirar um CPFException, dê um throws CadastrarException, e quando for mudar pro código do cliente, transforme para algum MinhaAplicaçãoException.

Com isso dito, nada te impede de repassar um SQLException ou qualquer outra lá para cima, se essa for a maneira que você trata a tua aplicação. Só há diversas maneiras de fazer a mesma coisa, nenhuma é absoluta.

Olá Bruno, boa noite! Obrigado por continuar acompanhando o tópico! :smiley:

Viraria um throws CadastraException, SQLException, IOException, ParseException, ClassNotFoundException, IllegalAccessException, e outras exceptions…

Vai atirando até vc perceber que a tua classe virou um Mega Zord, e que você está dando responsabilidades demais para ela.

Há um tempo atrás teve uma discussão no arquitetura de sistemas que também conversamos sobre isso. Uma maneira de evitar é saber que as camadas que chamaram o teu código não querem saber o que você está usando, nem as exceções que essas APIs atiram. Converta as exceções de camadas mais abaixo para exceções da sua camada, isso quando forem exceções que você não pode tratar e continuar com a tua vida.

Dito isso, continue a atirar um CPFException, dê um throws CadastrarException, e quando for mudar pro código do cliente, transforme para algum MinhaAplicaçãoException.

Com isso dito, nada te impede de repassar um SQLException ou qualquer outra lá para cima, se essa for a maneira que você trata a tua aplicação. Só há diversas maneiras de fazer a mesma coisa, nenhuma é absoluta.
[/quote]

Me desculpa mas vamos ver se entendi: No ClienteControl você está me sugerindo para continuar atirando CPFException e fazer o throws de CadastrarCliente? Isso para não quebrar o princípio de atirar a Exception mais específica, correto? Veja o código:

Controle

public class ClienteControl {   
       
   private Cliente cli = null;   
   
   ClienteControl(Cliente cli) {   
      this.cli = cli;   
   }
   
   public void executar(String nome, String cpf) throws CadastraException { // AQUI FOI ALTERADO era: throws Exception
      try {
         if(!Util.validaCPF(cpf))
            throw new CPFException();
         cli.setCPF(cpf);
         cli.setNome(nome);
      }
         catch(CadastraException e) { // AQUI FOI ALTERADO era: catch(Exception e)
            throw e;
         }
   }    
}

Então, a dúvida: Mas e se no try{} do código acima eu tiver uma chamada CliDAO.cadastrar() e ele me retornar uma exceção? Como vou tratá-la?
No CPF eu recebo um boolean e a partir dele gero a exceção correta. Mas e se o restorno for uma exceção, como vou fazer?

Desculpa a minha ignorância Bruno é que realmente sou um aprendiz em JAVA meu conhecimento é mínimo! Tento fazer o possivel para entender lendo tutoriais, artigos mas realmente muitas vezes empaco! :frowning: Peço desculpa antecipadamente e se puder continuar ajudando, fico muito feliz! :smiley:

E A TODOS QUE QUISEREM PARTICIPAR, participem! :wink: [color=blue]Obrigado.[/color]

Eu me considero um aprendiz também. Acho que vou chegar até o final da vida ainda achando que não sei o suficiente. :slight_smile:

Não. Considere como seu código fosse um framework, no sentido que as pessoas utilizam a API do teu aplicativo para poder rodar as coisas delas. O que estou falando é que haverá pelo menos uma exceção genérica da tua aplicação que encapsulará a maioria das outras. Enquanto você estiver dentro da tua própria aplicação, você pode usar as exceções que quiser, em qualquer quantidade, porém esta exceção genérica é mais utilizada para marcar “fronteira entre nações”.

Outro sentido que dou para utilizar “API do teu aplicativo”, é o exemplo da fronteira entre a interface e o núcleo da aplicação, seja a interface web, desktop, webservice, ou outro cliente, o núcleo é sempre o mesmo. Em termos MVC, é a fronteira entre o View+Controller com a do Model.

Note que uma coisa que eu não estou falando é que o cliente deverá se contentar com a exceção genérico, e ficar sem opções. Dá muito bem para descobrir qual foi a exceção específica lançada, desde que não a escondemos. Fala isso por que ainda dá para o teu controller decidir o que ele quer fazer dependendo da exceção lançada.

[quote=pedromuyala]
Controle

public class ClienteControl {   
       
   private Cliente cli = null;   
   
   ClienteControl(Cliente cli) {   
      this.cli = cli;   
   }
   
   public void executar(String nome, String cpf) throws CadastraException { // AQUI FOI ALTERADO era: throws Exception
      try {
         if(!Util.validaCPF(cpf))
            throw new CPFException();
         cli.setCPF(cpf);
         cli.setNome(nome);
      }
         catch(CadastraException e) { // AQUI FOI ALTERADO era: catch(Exception e)
            throw e;
         }
   }    
}

Então, a dúvida: Mas e se no try{} do código acima eu tiver uma chamada CliDAO.cadastrar() e ele me retornar uma exceção? Como vou tratá-la?
No CPF eu recebo um boolean e a partir dele gero a exceção correta. Mas e se o restorno for uma exceção, como vou fazer?[/quote]

1º, remova o try/catch, não servem de nada se você não está tratando alguma coisa.
2º, este código faz parte do model, não do controller. Digo isso por que você está implementando de regras de negócio.

Sobre como tratar, pode fazer do jeito que quiser 8) A pergunta é, o que você quer fazer? Encapsular as exceções em outra? Deixar ela passar? Tratar e tentar se recuperar do que aconteceu? Há algo que você não quer fazer? Não há uma resposta certa, só há decisões, ou pelo menos um objetivo final.