Eu li em muitos sites. Opcional deve ser usado apenas como um tipo de retorno e não usado em argumentos de método. Estou lutando para encontrar uma razão lógica. Por exemplo, eu tenho um pedaço de lógica que possui 2 parâmetros opcionais. Portanto, acho que faria sentido escrever minha assinatura de método assim (solução 1):
public int calculateSomething(Optional<String> p1, Optional<BigDecimal> p2 {
// my logic
}
Muitas páginas da Web especificam Opcional não devem ser usadas como argumentos de método. Com isso em mente, eu poderia usar a seguinte assinatura de método e adicionar um comentário claro do Javadoc para especificar que os argumentos podem ser nulos, esperando que futuros mantenedores leiam o Javadoc e, portanto, sempre realizem verificações nulas antes de usar os argumentos (solução 2) :
public int calculateSomething(String p1, BigDecimal p2) {
// my logic
}
Como alternativa, eu poderia substituir meu método por quatro métodos públicos para fornecer uma interface melhor e tornar mais óbvio que p1 e p2 são opcionais (solução 3):
public int calculateSomething() {
calculateSomething(null, null);
}
public int calculateSomething(String p1) {
calculateSomething(p1, null);
}
public int calculateSomething(BigDecimal p2) {
calculateSomething(null, p2);
}
public int calculateSomething(String p1, BigDecimal p2) {
// my logic
}
Agora, tento escrever o código da classe que invoca esse pedaço de lógica para cada abordagem. Primeiro, recupero os dois parâmetros de entrada de outro objeto que retorna Optional
s e depois invoco calculateSomething
. Portanto, se a solução 1 for usada, o código de chamada ficaria assim:
Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
int result = myObject.calculateSomething(p1, p2);
se a solução 2 for usada, o código de chamada ficaria assim:
Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
int result = myObject.calculateSomething(p1.orElse(null), p2.orElse(null));
se a solução 3 for aplicada, eu poderia usar o código acima ou o seguinte (mas é significativamente mais código):
Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
int result;
if (p1.isPresent()) {
if (p2.isPresent()) {
result = myObject.calculateSomething(p1, p2);
} else {
result = myObject.calculateSomething(p1);
}
} else {
if (p2.isPresent()) {
result = myObject.calculateSomething(p2);
} else {
result = myObject.calculateSomething();
}
}
Portanto, minha pergunta é: Por que é considerado uma prática ruim usar Optional
s como argumentos de método (consulte a solução 1)? Parece a solução mais legível para mim e torna mais óbvio que os parâmetros podem estar vazios / nulos para futuros mantenedores. (Estou ciente de que os designers Optional
pretendem que ele seja usado apenas como um tipo de retorno, mas não consigo encontrar razões lógicas para não usá-lo nesse cenário).
null
?