Usei o spring boot para desenvolver um projeto de shell usado para enviar email, por exemplo
sendmail -from foo@bar.com -password foobar -subject "hello world" -to aaa@bbb.com
Se os argumentos from
e password
estiverem ausentes, eu uso um remetente e uma senha padrão, por exemplo, [email protected]
e 123456
.
Portanto, se o usuário passar o from
argumento, ele também deve passar o password
argumento e vice-versa. Ou seja, ambos são não nulos ou ambos são nulos.
Como verifico isso com elegância?
Agora meu caminho é
if ((from != null && password == null) || (from == null && password != null)) {
throw new RuntimeException("from and password either both exist or both not exist");
}
From
endereço de email nem sempre é o nome da autenticação SMTP.Respostas:
Existe uma maneira de usar o operador
^
( XOR ):A
if
condição será verdadeira se apenas uma variável for nula.Mas acho que geralmente é melhor usar duas
if
condições com diferentes mensagens de exceção. Você não pode definir o que deu errado usando uma única condição.É mais legível e muito mais fácil de entender, e leva apenas um pouco de digitação extra.
fonte
!=
dois bools?!=
. Mindblown. E esse é um número muito alto de votos no comentário. E, para adicionar qualidade a este comentário, sim, também acho melhor dar uma mensagem de erro diferente para diferentes casos de erro, pois o usuário saberá melhor como corrigir o erro.if
cláusulas - a mensagem na exceção documenta muito bem (editei a pergunta, mas ela não aparecerá até ser aceita)Bem, parece que você está tentando verificar se a condição de "nulidade" dos dois é a mesma ou não. Você poderia usar:
Ou torne mais explícito as variáveis auxiliares:
fonte
^
faz. :-)^
diz "Ei, meus operandos são booleanos" de uma maneira que!=
não. (Embora esse efeito seja infelizmente diminuído pela necessidade de verificar "meus operandos podem ser numéricos e, talvez, eu não seja um operador relacional neste momento", o que eu concordo é uma desvantagem). Seu status de herói undiminished, apesar de discordar de mim :-)from
epassword
ambos devem ser nulos ou ambos não serão nulos". Talvez seja apenas eu e minha inexperiência, mas prefiro a solução mais legível como na resposta do @ stig-hemmer, mesmo que custe mais três linhas de código. Eu acho que simplesmente não entendo imediatamentebool != bool
- não é intuitivo.^
operador é um operador bit a bit; na verdade, não implica que seus operandos sejam booleanos. O operador booleano xor éxor
.Pessoalmente, prefiro legível a elegante.
fonte
IllegalArgumentException
vez de um bareRuntimeException
)Coloque essa funcionalidade em um método de 2 argumentos com a assinatura:
Isso economiza espaço no método real em que você está interessado e o torna mais legível. Não há nada errado com nomes de métodos ligeiramente detalhados e não há nada errado com métodos muito curtos.
fonte
((from == null) != (password == null))
é muito simples de entender também. Há algo errado com métodos não úteis.Uma solução Java 8 seria usada
Objects.isNull(Object)
, assumindo uma importação estática:Para Java <8 (ou se você não gosta de usar
Objects.isNull()
), pode escrever facilmente seu próprioisNull()
método.fonte
from == null != password == null
mantém tudo no mesmo quadro da pilha, mas usandoObjects.isNull(Object)
desnecessariamente empurra e aparece dois quadros. Objects.isNull (Object) existe porque 'Este método existe para ser usado como um Predicado' (ou seja, em fluxos).Objects.isNull()
- você pode escrever o seu próprio, se preferir -, mas no que diz respeito à legibilidade, acho que usarisNull()
é melhor. Além disso você precisa parênteses adicionais para tornar o simples compilação expressão:from == null != (password == null)
.(val == null)
é a facilidade oferecida com o objetivo de comparar com nulo, acho difícil superar duas invocações de métodos grandes e gordos me encarando, mesmo que o método seja bastante funcional, in-lineable e bem- nomeado. Mas sou apenas eu. Decidi recentemente que sou meio estranha.Aqui está uma solução geral para qualquer número de verificações nulas
Usos
fonte
Como você deseja fazer algo especial (use padrões) quando o remetente e a senha estiverem ausentes, lide com isso primeiro.
Depois disso, você deve ter um remetente e uma senha para enviar um email; lance uma exceção se alguma delas estiver faltando.
Um benefício adicional é que, se um de seus padrões for nulo, isso também será detectado.
Dito isto, em geral , acho que o uso do XOR deve ser permitido quando esse é o operador que você precisa. Ele é uma parte da língua, não apenas algum truque que funciona por causa de um arcano compilador de bug.
Certa vez, tive um cow-orker que achou o operador ternário muito confuso para usar ...
fonte
Gostaria de sugerir outra alternativa, que é como eu realmente escreveria esse pedaço de código:
Para mim, essa parece ser a maneira mais natural de expressar essa condição, o que facilita a compreensão para alguém que possa ter que lê-la no futuro. Ele também permite que você envie mensagens de diagnóstico mais úteis e trate a senha desnecessária como menos grave, além de facilitar a modificação, o que é bastante provável para essa condição. Ou seja, você pode descobrir que fornecer uma senha como argumento da linha de comando não é a melhor ideia e pode permitir a leitura da senha da entrada padrão opcionalmente, se o argumento estiver ausente. Ou você pode ignorar silenciosamente o argumento da senha supérflua. Alterações como essas não exigiriam que você reescrevesse tudo.
Além disso, ele executa apenas o número mínimo de comparações, portanto, não é mais caro que as alternativas mais "elegantes" . Embora o desempenho seja muito improvável aqui, porque iniciar um novo processo já é muito mais caro do que uma verificação nula extra.
fonte
Eu acho que uma maneira correta de lidar com isso é considerar três situações: 'from' e 'password' são fornecidas, nem são fornecidas, uma mistura das duas é fornecida.
Parece que a pergunta original quer interromper o fluxo se for uma entrada incorreta, mas eles terão que repetir parte da lógica posteriormente. Talvez uma boa declaração de lançamento seja:
fonte
Aqui está uma maneira relativamente direta que não envolve Xs e longos ifs. No entanto, exige que você seja um pouco mais detalhado, mas, de cabeça para baixo, você pode usar as exceções personalizadas que sugeri para obter uma mensagem de erro mais significativa.
fonte
Ninguém parece ter mencionado o operador ternário :
Funciona bem para verificar essa condição específica, mas não generaliza bem as duas variáveis passadas.
fonte
^
,!=
com dois bools ou doisif
sa == null ? (b == null? "both null" : "a null while b is not") : (b ==null? "b null while a is not")
Pelo que vejo suas intenções, não há necessidade de sempre verificar ambas as nulidades exclusivas, mas verificar se
password
é nulo se e somente sefrom
não for nulo. Você pode ignorar opassword
argumento fornecido e usar seu próprio padrão sefrom
for nulo.Escrito em pseudo deve ser assim:
fonte
password
sem fornecerfrom
, ele pode ter a intenção de substituir a senha, mas manter a conta padrão. Se o usuário fizer isso, é uma instrução inválida e deve ser informada. O programa não deve continuar como se a entrada fosse válida e prosseguir e tentar usar a conta padrão com uma senha que o usuário não especificou. Eu juro por programas como esse.Estou surpreso que ninguém tenha mencionado a solução simples de fazer
from
epassword
campos de uma classe e passar uma referência a uma instância dessa classe:Aqui
from
pode ser nulo ou não nulo e, se não for nulo, os dois campos terão valores não nulos.Uma vantagem dessa abordagem é que o erro de tornar um campo, mas não o outro, nulo é acionado onde a conta é obtida inicialmente, não quando o código que a utiliza é executado. Quando o código que usa a conta é executado, é impossível que os dados sejam inválidos.
Outra vantagem dessa abordagem é mais legível, pois fornece mais informações semânticas. Além disso, é provável que você exija o nome e a senha juntos em outros lugares, para que o custo da definição de uma classe adicional seja amortizado por vários usos.
fonte
new Account(null, null)
lançará um NPE, mesmo que a conta com nome e senha nulos ainda seja válida.null
vez de umAccount
. Você não passarianull
para oAccount
construtor.