He leído en muchos sitios web. Opcional debe usarse solo como tipo de retorno y no en argumentos de método. Estoy luchando por encontrar una razón lógica por la cual. Por ejemplo, tengo una lógica que tiene 2 parámetros opcionales. Por lo tanto, creo que tendría sentido escribir la firma de mi método de esta manera (solución 1):
public int calculateSomething(Optional<String> p1, Optional<BigDecimal> p2 {
// my logic
}
Muchas páginas web especifican Opcional no deben usarse como argumentos de método. Con esto en mente, podría usar la siguiente firma del método y agregar un comentario claro de Javadoc para especificar que los argumentos pueden ser nulos, con la esperanza de que los futuros mantenedores lean el Javadoc y, por lo tanto, siempre realicen comprobaciones nulas antes de usar los argumentos (solución 2) :
public int calculateSomething(String p1, BigDecimal p2) {
// my logic
}
Alternativamente, podría reemplazar mi método con cuatro métodos públicos para proporcionar una interfaz más agradable y hacer que sea más obvio que p1 y p2 son opcionales (solución 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
}
Ahora trato de escribir el código de la clase que invoca esta pieza lógica para cada enfoque. Primero recupero los dos parámetros de entrada de otro objeto que devuelve Optional
sy luego invoco calculateSomething
. Por lo tanto, si se usa la solución 1, el código de llamada se vería así:
Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
int result = myObject.calculateSomething(p1, p2);
si se usa la solución 2, el código de llamada se vería así:
Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
int result = myObject.calculateSomething(p1.orElse(null), p2.orElse(null));
si se aplica la solución 3, podría usar el código anterior o podría usar lo siguiente (pero es significativamente más 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();
}
}
Entonces mi pregunta es: ¿Por qué se considera una mala práctica usar Optional
s como argumentos de método (ver solución 1)? Parece la solución más legible para mí y hace que sea más obvio que los parámetros podrían estar vacíos / nulos para futuros mantenedores. (Soy consciente de que los diseñadores Optional
pretendían que solo se usara como un tipo de retorno, pero no puedo encontrar ninguna razón lógica para no usarlo en este escenario).
null
?