Está retornando no início de uma função mais elegante do que uma instrução if?

StackOverflow https://stackoverflow.com/questions/355670

  •  21-08-2019
  •  | 
  •  

Pergunta

Eu e um colega tem uma disputa sobre qual dos seguintes é mais elegante. Não vou dizer quem é quem, por isso é imparcial. Que é mais elegante?

public function set hitZone(target:DisplayObject):void
        {
            if(_hitZone != target)
            {
                _hitZone.removeEventListener(MouseEvent.ROLL_OVER, onBtOver);
                _hitZone.removeEventListener(MouseEvent.ROLL_OUT, onBtOut);
                _hitZone.removeEventListener(MouseEvent.MOUSE_DOWN, onBtDown);

                _hitZone = target;

                _hitZone.addEventListener(MouseEvent.ROLL_OVER, onBtOver, false, 0, true);
                _hitZone.addEventListener(MouseEvent.ROLL_OUT, onBtOut, false, 0, true);
                _hitZone.addEventListener(MouseEvent.MOUSE_DOWN, onBtDown, false, 0, true);
            }
        }

... ou ...

public function set hitZone(target:DisplayObject):void
        {
            if(_hitZone == target)return;

            _hitZone.removeEventListener(MouseEvent.ROLL_OVER, onBtOver);
            _hitZone.removeEventListener(MouseEvent.ROLL_OUT, onBtOut);
            _hitZone.removeEventListener(MouseEvent.MOUSE_DOWN, onBtDown);

            _hitZone = target;

            _hitZone.addEventListener(MouseEvent.ROLL_OVER, onBtOver, false, 0, true);
            _hitZone.addEventListener(MouseEvent.ROLL_OUT, onBtOut, false, 0, true);
            _hitZone.addEventListener(MouseEvent.MOUSE_DOWN, onBtDown, false, 0, true);

        }
Foi útil?

Solução

Este é um daqueles casos em que não há problema em quebrar as regras (ou seja, melhores práticas). Em geral, você quer ter como alguns pontos de retorno em uma função possível. A razão prática para isso é que simplifica a leitura do código, pois você pode apenas supor sempre que cada função terá os seus argumentos, faça a sua lógica, e retornar o resultado. Colocar em retornos extras para vários casos tende a complicar a lógica e aumentar a quantidade de tempo necessário para ler e Grokar totalmente o código. Uma vez que seu código atinge a fase de manutenção, em seguida, vários retornos pode ter um enorme impacto sobre a produtividade dos novos programadores como eles tentam decifrar a lógica (o seu especialmente ruim quando os comentários são escassos e o código claro). O problema cresce exponencialmente em relação ao comprimento da função.

Então, por, neste caso, é que todos preferem a opção 2? É porque você está a criação de um contrato que a função Enforces através de validação de dados de entrada, ou outros invariantes que talvez precisem ser verificados. A sintaxe mais bonita para a construção da validação é a verificação de cada condição, retornando imediatamente se a condição de falha validade. Dessa forma, você não tem que manter algum tipo de isValid boolean através de todos os seus cheques.

Para resumir as coisas: estamos realmente olhando como escrever código de validação e lógica não geral; opção 2 é melhor para o código de validação.

Outras dicas

Na maioria dos casos, o retorno precoce reduz a complexidade e torna o código mais legível.

É também uma das técnicas aplicadas na Spartan programação :

No mínimo o uso de Controle

  1. Minimizar o uso de condicionais por usando especializada constrói tal ternarization, herança, e classes tais como Classe Padrões, Classe e Classe Uma vez Separador
  2. Simplificar condicionais com return cedo.
  3. A minimização do uso de construções de laço, usando ação aplicador classes, como classe separada e Classe FileSystemVisitor.
  4. Simplificar lógica de iteração com saídas precoces (via return, continue e break declarações).

No seu exemplo, eu iria escolher a opção 2, uma vez que torna o código mais legível. Eu uso a mesma técnica ao verificar os parâmetros de função.

Enquanto os primeiros resultados são organizados como um bloco na parte superior do corpo da função / método, então eu acho que eles são muito mais legível do que adicionar outra camada de assentamento.

Eu tento evitar retornos precoces no meio do corpo. Às vezes, eles são a melhor maneira, mas na maioria das vezes eu acho que eles complicar.

Além disso, como regra geral, eu tentar minimizar estruturas de controle de nidificação. Obviamente, você pode levar um presente muito longe, então você tem que usar algum critério. Convertendo aninhados se de a um único switch / case é muito mais claro para mim, mesmo se os predicados repetir algumas sub-expressões (e assumindo que este não é um loop crítica desempenho numa língua burro demais para fazer eliminação subexpressão). Particularmente eu não gosto da combinação de ifs aninhados em corpos função / método longos, uma vez que se você pular para o meio do código, por algum motivo você acaba rolando para cima e para baixo para mentalmente reconstruir o contexto de uma determinada linha.

Na minha experiência, o problema com o uso primeiros resultados de um projeto é que, se os outros no projeto não são usados ??para eles, eles não vão olhar para eles. Tão cedo retornos ou não -. Se houver vários programadores envolvidos, certifique-se de todo mundo, pelo menos conscientes da sua presença

I Código pessoalmente gravação para voltar assim que puder, como atrasar um retorno muitas vezes introduz extra de complexidade por exemplo, tentando sair com segurança um monte de loops e condições aninhadas.

Então, quando eu olhar para uma função desconhecida, a primeira coisa que faço é olhar para todos os returns. O que realmente ajuda existe para configurar a sua coloração de sintaxe para dar return uma cor diferente de qualquer outra coisa. (I ir para o vermelho). Dessa forma, os returns-se uma ferramenta útil para determinar que a função faz, ao invés de obstáculos escondidos para os incautos.

Ah o guardião.

Imho, sim - a lógica do que é mais claro porque o retorno é explícito e ao lado da condição, e pode ser muito bem agrupado com estruturas semelhantes. Isto é ainda mais aplicável quando "retorno" é substituído por "throw new Exception".

Como disse antes, retorno precoce é mais legível, especialmente se o corpo de uma função é longo, você pode achar que a exclusão de um} por engano em uma função 3 página (wich em si não é muito elegante) e tentar compilar pode demorar vários minutos de depuração não-automatizável.

Ele também torna o código mais declarativa, porque essa é a maneira como você descreveria a outro ser humano, por isso, provavelmente, um desenvolvedor é perto o suficiente para um para compreendê-lo.

Se a complexidade da função aumenta mais tarde, e você tem bons testes, você pode simplesmente embrulhar cada alternativa em uma nova função, e chamá-los em ramos de caso, de que maneira você mantain o estilo declarativa.

Neste caso (um teste, nenhuma cláusula else) I como o teste-e-volta. Ele deixa claro que, nesse caso, não há nada a fazer, sem ter que ler o resto da função.

No entanto, esta é a divisão a mais fina de cabelos. Tenho certeza que você deve ter problemas maiores para se preocupar:)

opção 2 é mais legível, mas a capacidade de gerenciamento do código de falha quando um outro lugar pode ser obrigado a ser adicionado.

Então, se você tem certeza, não há movimento mais para a opção 2, mas se poderia haver espaço para uma condição de pessoa, então eu preferiria a opção 1

A opção 1 é melhor, porque você deve ter um número mínimo de pontos de retorno no procedimento. Há exceções, como

  if (a) {
    return x;
  }
  return y;

causa da maneira como funciona uma linguagem, mas em geral é melhor ter o menor número de pontos de saída, uma vez que é viável.

Eu prefiro evitar um retorno imediato no início de uma função, e sempre que possível colocar a lógica de qualificação para evitar a entrada para o método antes de ser chamado. Claro, isso varia dependendo da finalidade do método.

No entanto, eu não me importo de voltar no meio do método, desde que o método é curto e legível. No caso em que o método é grande, em minha opinião, já não é muito legível, de modo que ele quer ser reformulado em múltiplas funções com retornos em linha, ou eu vou explicitamente romper com a estrutura de controle com um único retorno no final.

Eu estou tentado a fechar-lo como cópia exata, como eu vi alguns tópicos semelhantes já, incluindo Invert‘if’para reduzir assentamento que tem boas respostas.

Vou deixá-lo viver agora ... ^ _ ^

Para fazer com que uma resposta, eu sou um crente que o retorno cedo como cláusula de guarda é melhor do que ifs profundamente aninhadas.

Eu tenho visto os dois tipos de códigos e eu prefiro primeiro como é aparência facilmente legível e compreensível para mim, mas eu li muitos lugares que existem precoce é a melhor maneira de ir.

Há pelo menos uma outra alternativa. Separar os detalhes do trabalho real da decisão sobre a possibilidade de realizar o trabalho. Algo como o seguinte:

public function setHitZone(target:DisplayObject):void
    {
        if(_hitZone != target)
            setHitZoneUnconditionally(target);

    }

public function setHitZoneUnconditionally(target:DisplayObject):void
    {
        _hitZone.removeEventListener(MouseEvent.ROLL_OVER, onBtOver);
        _hitZone.removeEventListener(MouseEvent.ROLL_OUT, onBtOut);
        _hitZone.removeEventListener(MouseEvent.MOUSE_DOWN, onBtDown);

        _hitZone = target;

        _hitZone.addEventListener(MouseEvent.ROLL_OVER, onBtOver, false, 0, true);
        _hitZone.addEventListener(MouseEvent.ROLL_OUT, onBtOut, false, 0, true);
        _hitZone.addEventListener(MouseEvent.MOUSE_DOWN, onBtDown, false, 0, true);

    }

Qualquer um destes três (o dois mais a terceira acima) são razoáveis ??para casos como pequeno como este. No entanto, seria uma coisa má para ter uma função centenas de linhas longas com vários "pontos de bail-out" polvilhadas durante todo.

Eu tive esse debate com o meu próprio código ao longo dos anos. I começou a vida favorecendo um retorno e, lentamente, ter caducado.

Neste caso, eu prefiro a opção 2 (um retorno) simplesmente porque estamos apenas falando de 7 linhas de código envolto por um if () com nenhum outro complexidade. É muito mais legível e função semelhante. Ela flui de cima para baixo. Você sabe que você começar no topo e no final na parte inferior.

Dito isto, como já foi dito, se houvesse mais guardas no início ou mais complexidade ou se a função cresce, então eu preferiria a opção 1:. Retorno imediatamente no início para uma validação simples

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top