Considere uma função sem parâmetros ( editar: não necessariamente) que executa uma única linha de código e é chamada apenas uma vez no programa (embora não seja impossível que seja necessário novamente no futuro).
Pode realizar uma consulta, verificar alguns valores, fazer algo que envolva regex ... qualquer coisa obscura ou "hacky".
A lógica por trás disso seria evitar avaliações dificilmente legíveis:
if (getCondition()) {
// do stuff
}
Onde getCondition()
é a função de uma linha.
Minha pergunta é simples: essa é uma boa prática? Parece bom para mim, mas não sei a longo prazo ...
getCondition
? Se é tão pequeno e pouco usado como você diz, então dar um nome a ela não está conseguindo nada.Respostas:
Depende dessa linha. Se a linha é legível e concisa por si só, a função pode não ser necessária. Exemplo simplista:
OTOH, se a função der um bom nome a uma linha de código que contém, por exemplo, uma expressão complexa e de difícil leitura, é perfeitamente justificada (para mim). Exemplo artificial (dividido em várias linhas para facilitar a leitura aqui):
fonte
taxPayer
é global neste cenário. Talvez essa classe sejaTaxReturn
etaxPayer
seja um atributo.Sim, isso pode ser usado para satisfazer as melhores práticas. Por exemplo, é melhor que uma função com nome claro faça algum trabalho, mesmo que tenha apenas uma linha, do que ter essa linha de código em uma função maior e precisar de um comentário em uma linha explicando o que faz. Além disso, as linhas de código vizinhas devem executar tarefas no mesmo nível de abstração. Um contraexemplo seria algo como
Nesse caso, é definitivamente melhor mover a linha do meio para uma função com nome sensato.
fonte
petrolFlag |= 0x006A;
sem qualquer tipo de tomada de decisão, seria melhor simplesmente dizerpetrolFlag |= A_B_C;
sem uma função adicional. Presumivelmente,engageChoke()
só deve ser chamado sepetrolFlag
atender a um determinado critério e que deve dizer claramente 'Preciso de uma função aqui'. Apenas um pequeno detalhe, esta resposta é basicamente pontual :)mixLeadedGasoline()
, você não precisaria!Eu acho que, em muitos casos, essa função é de bom estilo, mas você pode considerar uma variável booleana local como alternativa nos casos em que você não precisa usar essa condição em algum lugar em outros lugares, por exemplo:
Isso dará uma dica para o leitor de código e evitará a introdução de uma nova função.
fonte
IsEngineReadyUnlessItIsOffOrBusyOrOutOfService
).Além da resposta de Peter , se essa condição precisar ser atualizada em algum momento no futuro, encapsulando a maneira como você sugere que você teria apenas um único ponto de edição.
Seguindo o exemplo de Pedro, se este
torna-se isso
Você faz uma única edição e é atualizada universalmente. Manutenção sábio, este é um plus.
Em termos de desempenho, a maioria dos compiladores otimizadores removerá a chamada de função e alinhará o pequeno bloco de código de qualquer maneira. A otimização de algo assim pode reduzir o tamanho do bloco (excluindo as instruções necessárias para a chamada de função, retorno, etc.), portanto é normalmente seguro fazer isso mesmo em condições que poderiam impedir a inclusão.
fonte
seemsGreen
não ser confiável com objetos leves será irrelevante se o código nunca se importar se objetos leves são verdes. Se a definição de "leve" for alterada, no entanto, de modo que alguns objetos não verdes que retornam true paraseemsGreen
não sejam relatados como "leve", essa alteração na definição de "leve" poderá quebrar o código que testa objetos sendo Verde". Em alguns casos, testar o verde e o peso juntos no código pode tornar a relação entre os testes mais clara do que se fossem métodos separados.Além da legibilidade (ou em complemento), isso permite escrever funções no nível adequado de abstração.
fonte
Depende. Às vezes, é melhor encapsular uma expressão em uma função / método, mesmo que seja apenas uma linha. Se é complicado ler ou você precisar dele em vários lugares, considero uma boa prática. A longo prazo, é mais fácil manter, pois você introduziu um único ponto de mudança e melhor legibilidade .
No entanto, às vezes é apenas algo que você não precisa. Quando a expressão é fácil de ler de qualquer maneira e / ou aparece em um só lugar, não a envolva.
fonte
Eu acho que se você tiver apenas alguns deles, tudo bem, mas o problema surge quando há muitos deles no seu código. E quando o compilador é executado ou o interpitor (dependendo do idioma que você usa), está indo para essa função na memória. Então, digamos que você tenha três deles, acho que o computador não notará, mas se você começar a ter centenas dessas pequenas coisas, o sistema precisará registrar funções na memória que são chamadas apenas uma vez e depois não destruídas.
fonte
Recentemente, fiz exatamente isso em um aplicativo que refatorei, para tornar explícito o significado real do código sem comentários:
fonte
if
curto? Essa abordagem local (lambda) torna aPaymentButton_Click
função (como um todo) mais difícil de ler. OlblCreditCardError
exemplo parece ser um membro, assim tambémHaveError
é um predicado (privado) válido para o objeto. Eu tenderia a rebaixar isso, mas não sou programador em C #, então resisto.CheckInputs()
???Mover essa linha para um método bem nomeado facilita a leitura do código. Muitos outros já mencionaram isso ("código de auto-documentação"). A outra vantagem de movê-lo para um método é que facilita o teste de unidade. Quando é isolado em seu próprio método e testado por unidade, você pode ter certeza de que se / quando um bug for encontrado, ele não estará nesse método.
fonte
Já existem muitas respostas boas, mas há um caso especial que vale a pena mencionar .
Se a sua declaração de uma linha precisar de um comentário e você conseguir identificar claramente (o que significa: nome) seu objetivo, considere extrair uma função enquanto aprimora o comentário no documento da API. Dessa forma, você torna a chamada de função mais fácil e rápida de entender.
Curiosamente, o mesmo pode ser feito se atualmente não houver nada a fazer, mas um comentário lembrando as expansões necessárias (em um futuro muito próximo 1) ), então,
poderia muito bem mudou para isso
1) você deve ter certeza disso (consulte o princípio YAGNI )
fonte
Se o idioma suportar, eu normalmente uso funções anônimas rotuladas para fazer isso.
IMHO, esse é um bom compromisso, pois oferece o benefício de legibilidade por não ter a expressão complicada bagunçando a
if
condição, evitando bagunçar o espaço de nomes global / pacote com pequenos rótulos descartáveis. Tem o benefício adicional de que a função "definição" esteja exatamente onde está sendo usada, facilitando a modificação e a leitura da definição.Não precisa ser apenas funções predicadas. Também gosto de envolver repetidamente a placa da caldeira em pequenas funções como esta (funciona particularmente bem na geração de listas python sem sobrecarregar a sintaxe do colchete). Por exemplo, o seguinte exemplo simplificado ao trabalhar com PIL em python
fonte
[] == False
ou de algum outro equivalência pitônica semelhante que nem sempre é intuitiva. É basicamente uma maneira de sinalizar que alguma Condição é, de fato, um predicado.[] != False
, mas[]
é falso como quando convertido para um boollen([complicated expression producing a list]) == 0
do que usar oTrue if [blah] else False
que ainda exige que o leitor saiba que [] avalia False.