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 Optionals 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 Optionals 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 Optionalpretendem 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?