É uma prática ruim usar condicionais com funções que alteram o estado do programa?

4

O título pode ser um pouco vago, então deixe-me explicar. Vamos supor que temos uma função que faz alguma coisa (altera o estado do programa), por exemplo, uma função que cria um arquivo. Essa função retorna True se o arquivo for criado e False se o arquivo não for criado.

Agora, queremos usar essa função em um condicional, por exemplo:

if (createFile() == false)
    // log: we cannot create file

E também podemos fazer da seguinte maneira:

boolean fileCreated = createFile()
if (fileCreated == false)
    // log: we cannot create file

A questão é se o primeiro caso é pior que o segundo em termos de legibilidade e clareza e qual deles é recomendado para ser usado?

Meu raciocínio é que, porque alguém lendo o código pode não estar familiarizado com os componentes internos da função, no primeiro caso ele pode assumir que a função createFile () não altera o estado (uma vez que essas funções são predicadas)?

    
por leonz 26.03.2018 / 15:52
fonte

5 respostas

4

É um pouco de julgamento, mas eu diria que se você precisar chamar createFile() no início de um método, é um pouco melhor armazenar o resultado em uma variável. Isso porque, se alguém atualizar o código posteriormente e precisar verificar o estado fileCreated , é comum copiar a condição do bloco de código existente. Se você usar o método diretamente, o editor precisará introduzir a variável e atualizar a condição existente. Não é realmente o fim do mundo, então eu não ficaria preso a isso. Se a última declaração for return createFile() , não apresentarei uma variável.

Realmente, embora seja preferível não ter que verificar a mesma condição mais de uma vez em um método, evitando que seja inteiramente ideal. Isso tornaria o acima inútil. Então não é realmente uma coisa cortada e seca. Depende do nível de habilidade da equipe.

Relacionei, mas caso diferente é que, mesmo que o método não modifique nada, mas possa retornar resultados diferentes em chamadas diferentes, geralmente é necessário capturar o resultado localmente para correção.

    
por 26.03.2018 / 17:08
fonte
10

Para mim, o principal cheiro do código é que um método createFile() retorna um booleano indicando sucesso. Isso me lembra os estilos de programação dos anos 1970.

Um método denominado createFile() implica um contrato que cria o arquivo e, se não puder, o contrato não será atendido e o método deverá lançar uma exceção. Com a versão de retorno booleana, um usuário um pouco descuidado, acostumado com as práticas de programação atuais, verá esse nome e chamará o método, ignorando o valor de retorno booleano, e assumirá que o arquivo foi criado.

Se você quiser que o contrato permita a não criação de um arquivo em algumas circunstâncias, deverá indicar isso no nome, por exemplo, como createFileIfPossible() .

Normalmente, o código do usuário cria um arquivo porque é necessário para prosseguir, portanto, o tratamento de exceção padrão é o que você deseja, abortando toda a computação adicional até um local em que você saiba como continuar. Coloque uma captura lá e registre a exceção lá. Então não haverá mais necessidade do fragmento de código da sua pergunta.

    
por 26.03.2018 / 21:57
fonte
3

Usar diretamente o valor de retorno de uma função, em vez de salvá-lo em uma variável, é perfeitamente correto, se você só precisar dela uma vez. De fato, não introduzir artefatos supérfluos é uma boa idéia, pois assim você não pode perder o controle deles nem nomeá-los mal.

O que não está bem é o nome dessas funções. Eu não esperaria que ele retornasse um bool , mas um File ou qualquer outro, e lançaria uma exceção no fracasso. Em idiomas que apóiam, provavelmente deveria ser um ctor.
Como alternativa, renomear tryOpenFile() parece aceitável.
Outra estranheza é que não há argumento para o nome do arquivo.

    
por 26.03.2018 / 23:22
fonte
0

O código precisa ser fácil de ler. Se você fizer o desenvolvedor tentando encontrar o que realmente está acontecendo no seu código, há algo errado.

Ambos os casos são legíveis para mim, mas isso não significa que eles não possam ser melhorados. Eu entendo que o retorno de "criar arquivo" não é tão óbvio em termos de significado. Minha ideia é criar um novo método (em vez de uma variável) para tornar a leitura do código mais natural.

Então, você pode melhorar um pouco com:

if (!isFileCreated(createFile())
    // log: we cannot create file
    
por 26.03.2018 / 17:19
fonte
0

Ignore as chamadas reais por um segundo, porque elas são um detalhe de implementação e devem ser tratadas e assim por diante. Sua primeira tarefa é: Ou crie um arquivo e defina um booleano "fileCreated" como true, ou tente criar um arquivo mas falhe, limpe tudo como se você nunca tivesse tentou criar um arquivo e definir um "fileCreated" booleano como false.

Sua segunda tarefa é: Se o arquivo não foi criado, registre o fato.

Agora escreva o código da segunda tarefa. Você deve conseguir fazer isso sem ter escrito o código da primeira tarefa. Como resultado, você não pode ter uma condição como "if (createFile () == false). Seu primeiro exemplo de código vem junto com a criação do arquivo e o teste. Foi apenas um pequeno código, então você pode se safar , mas vai ficar feio em casos maiores.

    
por 07.04.2018 / 11:58
fonte