Dúvida arquitetural

Pessoal,

acho que vcs jah devem ter tido que resolver um problema do tipo:

  1. Usuario realiza uma consulta
  2. O sistema pode retornar a lista com os objetos da consulta ou a lista vazia com os possiveis motivos (Ex: Não há objetos com os parametros informados, usuario sem permissao de ver os objetos da lista).

Como vcs costumam tratar isso? Estou tratando lancando excepcoes especificas para cada caso quando não há objetos a serem retornados, mas tenho certeza que existem outras maneiras mais performaticas e elegantes.

So para visualizar melhor, vou por aki um trecho do problema:

Codigo do cliente:

...
 /** cliente realiza a chamada para buscar uma lista de livros importados (por exemplo) */
 try {
     Collection<Livro> livros =  manager.getLivrosImportados(idUsuario);
  }
 catch (SemPermissaoException spe) {
    // sera mostrado a lista vazia e o respectivo motivo
  }
  catch (blablaException spe) {
   // sera mostrado a lista vazia e o respectivo motivo
  }
  ...
  catch (maisumaException spe) {
  // sera mostrado a lista vazia e o respectivo motivo
  }
 
...

Codigo do servidor:

...
public Collection<Livro> getLivrosImportados(long idUsuario) {
    // verifca permissao
    if (!PermissaoUtil.verficaPermissao(idUsuario))
         throw new SemPermissaoException("usuario sem permissao");

    // verifica outra restricao...
    if (algumaCondicao)
      throw new blablaException("blablaException");
 
    // Serao lancadas tantas excecoes qto forem a quantidade de motivos,
   // pelos quais a lista podera vir vazia.... 
      
    Collection<Livro> livros = dao.getLivrosImportados();
  
    return livros;
}

[quote=marcosurata] Estou tratando lancando excepcoes especificas para cada caso quando não há objetos a serem retornados, mas tenho certeza que existem outras maneiras mais performaticas e elegantes.
[/quote]

Marcos, até me interessei por esse tópico porque trato assim também. Podem/deve haver maneiras mais elegantes, mas não acredito que possuam performance melhor (até porque o throw para a análise naquele ponto). Vamos ouvir outras opiniões…

abraços,

otávio

Este artigo explica bem meu ponto de vista:

[]'s

pois eh, eu sei que usar exceptions para fazer esse “controle de fluxo” não é adequado e tem um overhead grande, pois eh muito custoso ficar lancando exceptions para essas situações.

Por isso, eu perguntei como vcs costuma tratar as situações q mencionei de maneira mais elegante e mais performática.

Peço desculpas se ofendi na colocação do link, porém eu apenas quis colocar uma referência para o pessoal que está acompanhando o tópico e gostaria de aprender as boas práticas e não ensinar como deve ser feito.

[]'s

aleck, bom artigo. Principalmente na sugestão de extender a exception própria com métodos que permitam informações mais corretas (como a retornar um inteiro com a medida da gravidade do erro).

O texto apenas reforçou o meu pensamento (favor corrigir se eu estiver errado). Uma excessão deve ser lançada quando da quebra do contrato. Se um usuário, portanto, estiver tentando acessar uma parte bloqueada para ele, e for importante passar para ele a mensagem “acesso negado”, eu daria um throw na minha exception geral com a informação relevante.

Acho que a maior diferença é que eu tenho um mínimo possível de throws próprios e uso eles para separar as excessões “controladas” das fora de controle (por exemplo, separar de uma NullPointerException).

Sigo também a regra de informar o usuário apenas aquilo que ele pode mudar (por exemplo orientar o mesmo a se logar na aplicação). marcos, eu mudaria apenas o seguinte no seu fluxo. De:

catch (SemPermissaoException spe) {
     // sera mostrado a lista vazia e o respectivo motivo
   }
   catch (blablaException spe) {
    // sera mostrado a lista vazia e o respectivo motivo
   }
   ...
   catch (maisumaException spe) {
   // sera mostrado a lista vazia e o respectivo motivo
   }

Para:

   catch (MinhaException spe) {
   // sera mostrado a lista vazia e o respectivo motivo
   }

Onde o motivo variado só muda a informação do motivo. O que vocês acham?

abraços,

otávio

No exemplo acima, a resposta para o usuário será sempre a mesma: “lista vazia e o respectivo motivo”, não vejo a necessidade de replicar várias exceptions com o mesmo conteúdo e nomes diferentes.

Cabe ao desenvolvedor descobrir se o cliente realmente precisa de uma lista vazia com o motivo ou quer apenas o motivo. Em alguns casos nenhuma destas informações são relevantes para o cliente, sendo nteressante a nível de desempenho e manutenção ser lançada a seguinte exception:


throws new RuntimeException("Não foram encontrados livros importados");

Creio que a regra abaixo deve ser seguida na maioria dos casos:

Reação do Cliente                                Exception

Não pode fazer nada                            Unchecked

Cliente irá tomar ações                        Checked
com os dados fornecidos
pela exception

[]'s