none
Melhor prática para obter retorno de uma função. RRS feed

  • Pergunta

  • Pessoal,

    Estou com uma idéia e gostaria de saber a opinião de vcs, saber se é muita gambiarra ou não....hehehe....

    Se trata de criar um objeto que retorna o status de uma ação tomada, por exemplo, no banco de dados.

    Eis o cenário: Preciso gravar um cliente no banco, e para isto tenho que executar uma série de verificações antes de persistir os dados.
    Na prática são 6 IFs que tenho que executar para garantir que a regra de negócio está sendo aplicada. Cada "ELSE" significa uma mensagem de erro diferente que preciso retornar ao usuário. Se todas as validações executarem com sucesso e o cliente persistido no banco, não preciso retornar nada ao usuário, simplesmente redireciono-o para outra página.

    Pois bem, gostaria de saber de vcs qual seria a melhor prática para executar este método e obter o retorno desejado.
    A primeira idéia que tive foi declarar a função com retorno do tipo String, que devolverá o status da validação, porém não acho que esta seja a melhor forma.
    Pensei então em criar um objeto de retorno, algo do tipo RetornoCliente que contem uma propriedade boolean dizendo se a operação teve sucesso, e outra propriedade string informando o status do erro caso a propriedade anterior seja falsa.

    Qual a opinião de vcs? Como vcs resolveriam este problema?

    Obrigado a todos pela ajuda!

    segunda-feira, 9 de novembro de 2009 12:55

Respostas

  • Fala Fábio,

    Bem, eu faço da seguinte forma: O retorno da função não retorna nem uma string, nem um boolean + string... Eu crio uma classe que encapsula o resultado da função, e faço as funções retornarem uma instância da mesma. Algo assim:

    public class RetornoFuncao
    {
        private bool valido;
        private List<string> mensagens;

        public bool Valido
        {
            get { return this.valido; }
            set { this.valido = value; }
        }

        public List<string> Mensagens
        {
            get { return this.mensagens; }
            set { this.mensagens = value; }
        }

        public string Mensagem
        {
            get
            {
                StringBuilder sb = new StringBuilder();

                foreach (string var in this.mensagens)
                {
                    if (sb.ToString() != string.Empty)
                    {
                        sb.Append(Environment.NewLine);
                    }

                    sb.Append(var);
                }

                return sb.ToString();
            }
        }
    }

    Bem, você pode incrementar essa classe um pouco mais, se quiser. Fica só como sugestão.

    Forte abraço,

    André Borges Medeiros
    MCPD, MCT

    >> Se a resposta solucionar sua dúvida, favor Votar como Útil
    • Marcado como Resposta Fábio Moggi segunda-feira, 9 de novembro de 2009 15:53
    segunda-feira, 9 de novembro de 2009 14:04
  • Fábio,

    O problema é a complexidade que envolve este seu retorno de função, ainda mais retornando uma string.

    Se a idéia é efetivar um registro, o resultado esperado é que ele se efetive, e neste caso a não efetivação é sim um comportamento excepcional, independente da probabilidade de isto acontecer.

    Retornar valores de funções para este tipo de cenário vai ocasionar em aumento de complexidade do seu código.

    André,

    Exceções devem ser lançados quando o objetivo de um comportamento não pode ser atingido.
    Não existe problema de fluxo. O objeto está lá para fazer X. Se ele não pode fazer X porque ocorreu Y, e ele não pode fazer nada com Y, então ele lança uma exceção.

    Leandro,

    Sim, existe redução de perfórmance.

    Mas o que recomenda-se é: nunca otimize seu código prematuramente, pois otimizar envolve trade-offs, neste caso o seu você estaria trocando a simplicidade de seu código por um suposto ganho de perfórmance.
    []'s
    Rafael Noronha
    http://rafanoronha.net/
    @rafanoronha
    terça-feira, 10 de novembro de 2009 14:31

Todas as Respostas

  • Fala Fábio,

    Bem, eu faço da seguinte forma: O retorno da função não retorna nem uma string, nem um boolean + string... Eu crio uma classe que encapsula o resultado da função, e faço as funções retornarem uma instância da mesma. Algo assim:

    public class RetornoFuncao
    {
        private bool valido;
        private List<string> mensagens;

        public bool Valido
        {
            get { return this.valido; }
            set { this.valido = value; }
        }

        public List<string> Mensagens
        {
            get { return this.mensagens; }
            set { this.mensagens = value; }
        }

        public string Mensagem
        {
            get
            {
                StringBuilder sb = new StringBuilder();

                foreach (string var in this.mensagens)
                {
                    if (sb.ToString() != string.Empty)
                    {
                        sb.Append(Environment.NewLine);
                    }

                    sb.Append(var);
                }

                return sb.ToString();
            }
        }
    }

    Bem, você pode incrementar essa classe um pouco mais, se quiser. Fica só como sugestão.

    Forte abraço,

    André Borges Medeiros
    MCPD, MCT

    >> Se a resposta solucionar sua dúvida, favor Votar como Útil
    • Marcado como Resposta Fábio Moggi segunda-feira, 9 de novembro de 2009 15:53
    segunda-feira, 9 de novembro de 2009 14:04
  • Ficou um pouco abstrato o seu cenário, mas geralmente o recomendável é lançar exceções quando o resultado da operação não é o resultado esperado pelo cliente.

    Por exemplo ao persistir um objeto, o esperado é que a persistência funcione.
    Se não funcionar, você lança uma exceção, que pode ser tratada no código consumidor.
    []'s
    Rafael Noronha
    http://rafanoronha.net/
    @rafanoronha
    segunda-feira, 9 de novembro de 2009 15:04
  • Olá André,

    Obrigado por esclarecer a dúvida. À partir da sua sugestão vou incrementar conforme minha necessidade.

    Valeu pela força!!
    • Marcado como Resposta Fábio Moggi segunda-feira, 9 de novembro de 2009 15:53
    • Não Marcado como Resposta Fábio Moggi segunda-feira, 9 de novembro de 2009 15:53
    segunda-feira, 9 de novembro de 2009 15:49
  • Olá Rafael,

    Neste caso acredito que gerar Exceptions não seja a melhor opção.
    Sempre li e ouvi que Exceptions são custosas para o sistema e que devem somente ser lançadas para algo que seja inesperado, uma exceção(como por exemplo queda de link, banco de dados indisponível, etc)
    Neste caso já está previsto no fluxo de negócio a mensagem de erro caso os dados não sejam válidos, então não é uma exceção do sistema, e sim uma inconsistência dos dados.

    O que vc acha?


    Obrigado pela ajuda!
    segunda-feira, 9 de novembro de 2009 15:53
  • Oi pessoal,

    Realmente não é recomendável controlarmos o fluxo da sua aplicação com exceptions...
    Existem muitas discussões sobre isso, em uma pesquisa no Google podemos achar muitas ...

    Forte abraço,

    André Borges Medeiros
    MCPD, MCT

    >> Se a resposta solucionar sua dúvida, favor Votar como Útil
    segunda-feira, 9 de novembro de 2009 16:30
  • Esses dias vi o fonte de um aplicativo de um conhecido e ele utilizava exceptions como messagebox. Interessante, pelo menos, pois ele disparava um new MinhaExceptionEspecializada("texto") e no context travata essas exceptions com Caixas de Diálogo mais apresentáveis (tratadas). Gostaria de saber se alguém sabe se isso é prejudicial na performance ou não, se é uma boa prática ou não, e se o aconselhável é manter os Messagebox.Show ou podemos usar este método!

    Obrigado a todos
    "Any fool can write code that a computer can understand. Good programmers write code that humans can understand" (Martin Fowler)
    terça-feira, 10 de novembro de 2009 01:29
  • Bem eu não usaria a solução do Andre, no seu caso, pois é algo muito simples, o retorno de uma string já te atende, não tem porque complicar, este retorno, eu so usaria algo mais complexo se eu precisasse alocar varias mensagens de "erro" numa mesma operação, como por exemplo ao importar um txt ou um xls, em que cada linha do arquivo eu precisaria saber se teve sucesso ou se não importou.

    Se uma simples string te atende não vejo mal em retornar uma string, pq vc estaria retornando um objeto sendo que nesse objeto so teria uma string ?
    terça-feira, 10 de novembro de 2009 09:57
  • Rafael Noronha,

    não perco performance ao lançar uma exception? Sempre ouço que exceptions são "lentas".
    Isso é verdade?

    Abraços

    "Any fool can write code that a computer can understand. Good programmers write code that humans can understand" (Martin Fowler)
    terça-feira, 10 de novembro de 2009 11:06
  • Fábio,

    O problema é a complexidade que envolve este seu retorno de função, ainda mais retornando uma string.

    Se a idéia é efetivar um registro, o resultado esperado é que ele se efetive, e neste caso a não efetivação é sim um comportamento excepcional, independente da probabilidade de isto acontecer.

    Retornar valores de funções para este tipo de cenário vai ocasionar em aumento de complexidade do seu código.

    André,

    Exceções devem ser lançados quando o objetivo de um comportamento não pode ser atingido.
    Não existe problema de fluxo. O objeto está lá para fazer X. Se ele não pode fazer X porque ocorreu Y, e ele não pode fazer nada com Y, então ele lança uma exceção.

    Leandro,

    Sim, existe redução de perfórmance.

    Mas o que recomenda-se é: nunca otimize seu código prematuramente, pois otimizar envolve trade-offs, neste caso o seu você estaria trocando a simplicidade de seu código por um suposto ganho de perfórmance.
    []'s
    Rafael Noronha
    http://rafanoronha.net/
    @rafanoronha
    terça-feira, 10 de novembro de 2009 14:31
  • Rafael,

    você respondeu uma pergunta que postei ontem hehehe
    poderia inserir a resposta lá no outro tópico para que eu marque como respondida??

    Obrigado por sua explicação desde já. Nunca tinha visitado a parte de "Arquitetura" do fórum, e fiquei muito feliz ao ler algumas respostas aqui! É sempre muito bom ler explicações de quem sabe explicar e sabe como responder! Parabéns a todos! :)

    segue o link caso queira responder lá para finalizar o tópico.
    Abraços
    http://social.msdn.microsoft.com/Forums/pt-BR/arquiteturapt/thread/4498d263-493d-425b-a32a-aea9c99bfcbe
    "Any fool can write code that a computer can understand. Good programmers write code that humans can understand" (Martin Fowler)
    terça-feira, 10 de novembro de 2009 15:11
  • Olá Fábio,

    Ñ seria melhor voce primeiro executar a validação das regras de negócio em um método ?
    Caso não atenda alguma regra, voce retorna a mensagem para o usuário. Se validou tudo certinho, voce chama o método Salvar(). Acho mais simples e pratico para resolver o seu problema.

    Att,
    Edynilson
    • Sugerido como Resposta Edynilson quinta-feira, 19 de novembro de 2009 17:33
    quinta-feira, 19 de novembro de 2009 17:33