Se houver um método
bool DoStuff() {
try {
// doing stuff...
return true;
}
catch (SomeSpecificException ex) {
return false;
}
}
deveria ser chamado IsStuffDone()
?
Ambos os nomes podem ser mal interpretados pelo usuário: se o nome é DoStuff()
por que ele retorna um valor booleano? Se o nome for IsStuffDone()
, não está claro se o método executa uma tarefa ou apenas verifica seu resultado.
Existe uma convenção para este caso? Ou uma abordagem alternativa, como esta é considerada defeituosa? Por exemplo, em idiomas que possuem parâmetros de saída, como C #, uma variável de status booleana pode ser passada para o método como uma e o tipo de retorno do método void
.
EDIT: No meu problema particular, o tratamento de exceções não pode ser delegado diretamente ao chamador, porque o método faz parte de uma implementação de interface. Portanto, o chamador não pode ser acusado de lidar com todas as exceções de diferentes implementações. Não está familiarizado com essas exceções. No entanto, o chamador pode lidar com uma exceção personalizada, como StuffHasNotBeenDoneForSomeReasonException
sugerido na resposta e no comentário do npinti .
fonte
boolean
vez de quebrar ou passar a exceção quase sempre está errado.BadlyDesignedMethodInSeriousNeedOfRefactoring
? E para responder à sua pergunta sobre as exceções - eu deixaria o chamador lidar com elas ou as capturaria e, em seguida, lançaria uma exceção personalizada que significa "esse método não funciona". Compartilhe e curta.if (FirstMethodSucceeds(problem) or SecondMethodSucceeds(problem) or ...) Hurray(); else UniversalSolve(problem);
. Fazer o mesmo com exceções (personalizadas?) Seria inutilmente mais complicado.Respostas:
No .NET, você geralmente possui pares de métodos em que um deles pode gerar uma exceção (
DoStuff
) e o outro retorna um status booleano e, em execução bem-sucedida, o resultado real por meio de um parâmetro out (TryDoStuff
).(A Microsoft chama isso de "Padrão Try-Parse" , pois talvez o exemplo mais proeminente seja o
TryParse
método de vários tipos primitivos.)Se o
Try
prefixo é incomum no seu idioma, você provavelmente não deve usá-lo.fonte
if (TryDoStuff()) print("Did stuff"); else print("Could not do stuff");
é um idioma bastante padrão e intuitivo na minha opinião.TryDoStuff
se supõe que os métodos falham de maneira limpa e não têm efeito colateral quando retornam falsos.Remove
métodos, por exemplo, na estrutura .NET que removerão um elemento de uma estrutura de dados (por exemploDictionary
) e retornarão abool
. O consumidor da API pode decidir consumi-lo ou ignorá-lo. No entanto, os erros são relatados como exceções.E se você simplesmente lançou a exceção no código de chamada?
Dessa forma, você está delegando o tratamento de exceções para quem estiver usando seu código. E se, no futuro, você desejar fazer o seguinte:
FileNotFoundException
for lançada, execute a ação BSe você retroceder sua exceção, a alteração acima implicaria simplesmente a adição de um
catch
bloco extra . Se você deixar como está, precisará alterar o método e o local a partir do qual o método é chamado, que, dependendo da complexidade do projeto, pode estar em vários locais.fonte
DoStuff
falhar, lançar uma exceção para o caso de falha seria semelhante ao controle do fluxo do programa com exceções ruins. Exceções também têm um custo de desempenho inerente. SeDoStuff
falhar é um caso incomum devido a um erro, as exceções definitivamente são o caminho a seguir, como sugere o @npinti.DoStuff()
método do OP limpar após o código interno gerar uma exceção, e as Pós-condições do método ainda estiverem corretas, um código de retorno poderá ser uma opção melhor, pois o erro foi tratado.DoStuff()
é suficiente, e o valor retornado da função deve ser documentado, e você não precisa mencioná-lo no nome da função, procurando muitas API disponíveis:PHP
C-Sharp
fonte
Em Java, a API Collection define um método add que retorna um booleano. Basicamente, retorna se a adição alterou a coleção. Portanto, para um,
List
ele geralmente retornará verdadeiro, pois o item foi adicionado, enquanto para umSet
pode retornar falso, se o item já estiver lá, poisSet
s permite cada item único no máximo uma vez.Dito isto, se você adicionar um item que não é permitido pela coleção, por exemplo, um valor nulo, a adição lançará um em
NullPointerException
vez de retornar falso.Quando você aplica a mesma lógica ao seu caso, por que você precisa retornar um booleano? Se é para ocultar uma exceção, não. Basta lançar a exceção. Dessa forma, você pode ver o que deu errado. Se você precisar de um booleano, porque talvez não tenha sido feito, por algum outro motivo que não seja uma exceção, nomeie o método
DoStuff()
, pois isso representa o comportamento. Faz coisas.fonte
Pode falhar por diferentes razões, Exceção, condições normais, então usaria isso:
Importante é documentar o que o booleano significa.
fonte
Normalmente, tenho métodos que retornam um
OperationResult
(ouOperationResult<T>
) e definem aIsSuccess
propriedadeOperationResult
adequadamente. Se o método 'usual' for nulo, retorneOperationResult
, se o método 'usual' retornar um objeto, retorneOperationResult<T>
e defina aItem
propriedadeOperationResult
adequadamente. Eu também sugeriria ter métodosOperationResult
como.Failed(string reason)
e.Succeeded(T item)
.OperationResult
rapidamente se torna um tipo familiar em seus sistemas e os desenvolvedores sabem como lidar com isso.fonte
Realmente depende do idioma que você está usando. Como em alguns idiomas, existem convenções e protocolos que realmente não existem em muitos idiomas ou em nenhum deles.
Por exemplo, na linguagem Objective-C e no iOS / Mac OS X SDK, os nomes dos métodos geralmente seguem as seguintes linhas:
Como você pode ver, existe um método chamado viewDidLoad. Prefiro usar esse tipo de nomeação sempre que criar meus próprios aplicativos. Isso pode ser usado para verificar se algo deveria acontecer como você disse. Acredito que você esteja pensando profundamente sobre o que é o nome de seus métodos. A maioria dos métodos retorna o status do que eles fazem independentemente, por exemplo:
No PHP, mysql_connect () retornará false se a conexão falhar. Não diz que sim, mas sim, e a documentação diz que sim, para que não possa ser mal interpretada pelo programador.
fonte
Gostaria de sugerir o uso do prefixo 'Try'. Esse é um padrão bem conhecido para situações em que o método pode ter êxito ou não. Esse padrão de nomenclatura foi usado pela Microsoft no .NET Framework (por exemplo, TryParseInt).
Mas, talvez isso não seja sobre nomeação. É sobre como você projeta os parâmetros de entrada / saída do seu método.
Minha idéia é que, se um método tiver um valor de retorno, o objetivo de chamar esse método deve ser obter esse valor de retorno. Portanto, evite usar o tipo de retorno para indicar o status de uma operação.
Em C #, prefiro usar um parâmetro out. Usando uma saída, estou marcando o parâmetro como um parâmetro lateral. Especialmente que o C # 6 oferecerá suporte à declaração de variável embutida.
fonte
Eu escolheria um nome com base no papel principal do método. O fato de esse método retornar valor booleano não exige o prefixo 'Is'. Vamos ter um código Java, que usa o prefixo 'Is' bastante extensivamente. Dê uma olhada
java.io.File.delete()
. Ele retornaboolean
, mas não é chamadoisFileDeleted()
. O motivo é que a principal função do método é excluir um arquivo. Alguém chama esse método com a intenção de excluir um arquivo.O booleano existe apenas para comunicar de volta o resultado do trabalho. Por outro lado, vamos ver
java.util.Map.isEmpty()
. Obviamente, você chama esse método para descobrir se a coleção está vazia. Você não quer que nada seja feito. Você só quer descobrir qual é o estado atual.Então, pessoalmente, eu definitivamente ficaria
DoStuff()
.Esta é uma questão muito importante para mim. Muitas vezes, quando mantenho o código legado, deparo-me com algo que chamo pessoalmente de "método da mentira". O nome sugere a ação A, mas o corpo executa a ação B. O exemplo mais interessante é o método getter, que altera os dados no banco de dados.
fonte