Pergunta

Eu sou novo em programação, e estou querendo saber se existe uma maneira correta de pedir a sua lógica estrutura de controle.

Parece mais natural para verificar o caso mais provável em primeiro lugar, mas tenho a sensação de que algumas estruturas de controle não irá funcionar a menos que verificar tudo o que é falso para chegar a algo que é verdade (dedução lógica?)

Seria difícil de se adaptar a essa visão 'negativa', eu prefiro uma perspectiva mais positiva, presumindo tudo é verdadeiro:)

Foi útil?

Solução

Na maioria das situações, a legibilidade é mais importante do que a velocidade de execução. Por isso, tente para otimizar a facilidade de compreensão, usando a seguinte abordagem:

Todos os cheques "afirmação" é feito na frente. Isso garante que todos os casos errôneas são tratadas no início. isso é especialmente importante para Null-ponteiro-cheques, e.

    if(arg == null){ 
      throw new IllegalArgumentException();  // harsh (correct)
    }
    // or 
    if(arg == null){
        arg = "";  // forgiving (lazy)
    }

Em seguida, eu tento verificar se há uma condição única em cada instrução if. em vez de

    if(condition1 && condition2) {
        ...
    } else {
        ...
    }

i geralmente preferem

    if(condition1) {
        if(condition2) {
            ...
        } else {
            ...
        }
    } else {
        ...
    }

Esta abordagem é mais fácil para definir pontos de interrupção, e isso faz com que a lógica mais obvous.

Eu evito negações; em vez de

    if(! condition) {
        ...a...
    } else {
        ...b...
    }

coisas estão melhor rearranjadas para

    if(condition) {
        ...b...
    } else {
        ...a...
    }

Finalmente, todos os métodos que retornam um resultado boolean deve ter um nome "positivo" que indica quais os meios Resultados:

    boolean checkSomething(Something x){ ... }     // bad -- whats the result?
    boolean isSomethingInvalid(Something x){ ... } // better, but ...
    boolean isSomethingValid(Something x){ ... }   // best, no "mental negation"

Outras dicas

Há uma excelente discussão de apenas este tema em McConnell completar o código de . É um livro que eu recomendo. De qualquer forma a discussão relevante é nas páginas 706-708 da primeira edição ou pg. 749-750 da segunda edição (graças pedestal). A partir desse livro:

Organizar testes para que aquele que de mais rápido e mais provável que seja verdadeiro é realizada em primeiro lugar. Deve ser fácil de cair através do caso normal, e se existem ineficiências, que deveriam estar em processar as exceções.

Há coisas a considerar, além do valor da instrução de condição. Por exemplo, se os blocos de código são significativamente diferentes em tamanho, você pode querer colocar o bloco pequeno primeiro de modo que é mais fácil de ver. (Se o bloco maior é realmente grande, ele pode precisar de ser reformulado, ou talvez puxado para fora em um método separado.)

if( condition is true ) {
    do something small;
} else { 
    do something;
    and something else; 
    . . .
    and the 20th something;
}

Dentro da condição, sim, existem algumas línguas que vão parar avaliar uma expressão uma vez que uma parte é falsa. Isso é importante para se lembrar se você incluir algum tipo de lógica é definida no código: se a sua língua avalia a expressão inteira, você deve fazer isso:

if( variable is defined ) {
    if( variable == value ) {
        ...
    }
}

em vez do que isso:

if( (variable is defined) && (variable == value) ) {
     ...
}

Eu não acho que há uma maneira "correta" para projetar suas condições. Se você está trabalhando para uma empresa que tem padrões de codificação, você deve verificar para ver se isso está incluído nas normas. (O último lugar que eu trabalhei tinha um número razoável de padrões definidos, mas não especificou como escrever lógica condicional.)

Geralmente, eu iria verificar os itens inesperados em primeiro lugar, que me obriga a lidar com o fluxo excepcional do programa.

Assim, posso lançar exceções / abort operações antes de eu começar a "criação" para o fluxo normal do programa.

Eu aponto para estruturar as minhas condições de forma a minimizar a quantidade de informações que o leitor tem que tomar Às vezes é mais fácil de teste para o negativo para provar o positivo:.

Um exemplo - o teste para ver se um período de 2 datas cruza com outro período de 2 datas é mais fácil escrever como teste de não interseção de 2 períodos

Se é um simples sim ou erro pergunta, então eu normalmente estrutura as coisas de modo que o ramo de tratamento de erros é a cláusula else. Se é um sim ou não questão (ou seja, nem ramo é um erro), é puramente um julgamento sobre o que se sente mais natural. Se há um monte de testes que devem ser feitas antes do coração do código pode executar, eu costumo tentar estruturar as coisas de modo que os testes negativos vêm em primeiro lugar e de alguma forma ignorar o código que se segue (retorno da função, break ou continue a partir de um loop).

Either / Or. Eu geralmente uso a abordagem 'negativo' embora.

if (! Algo) {

}

Este é um pouco fora do âmbito da questão, mas geralmente você também quer que seus métodos para falhar rapidamente. Por esta razão eu tendem a fazer toda a minha validação de argumento no topo do método, mesmo que eu não vou usar o argumento até mais tarde no código. Isto fere a legibilidade, mas apenas no caso em que o método é muito longo (tem que rolar para fora da tela para vê-lo). Claro, isso é um cheiro de código em si mesmo e tende a ficar reformulado para fora.

Por outro lado, se o cheque não é simples e eu vou estar passando-lo para outro método que está indo só para verificá-lo de qualquer maneira, eu não vou repetir o código de verificação no método atual. Tal como acontece com a maioria das coisas, há um equilíbrio.

(Contexto: Java)

READABILITY1: Condição que resolve para um bloco menor de código vai em primeiro lugar

if (condition) {
  smallBlock();
} else {
  bigBlockStart();
  ........
  bigBlockEnd();
}

READABILITY2: afirmação positiva vai em primeiro lugar, como é mais fácil não notar um sinal de negação

fazer sentido:. Assert todas as pré-condições para um método que utiliza Assert.blabla () e uso de condicionais apenas para que o método faz

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