Ho letto su molti siti Web. Opzionale dovrebbe essere usato solo come tipo restituito e non usato negli argomenti del metodo. Sto lottando per trovare una ragione logica per cui. Ad esempio ho un pezzo di logica che ha 2 parametri opzionali. Quindi penso che avrebbe senso scrivere la mia firma del metodo in questo modo (soluzione 1):
public int calculateSomething(Optional<String> p1, Optional<BigDecimal> p2 {
// my logic
}
Molte pagine Web specificano Opzionale non devono essere utilizzate come argomenti del metodo. Con questo in mente, potrei usare la seguente firma del metodo e aggiungere un commento Javadoc chiaro per specificare che gli argomenti possono essere nulli, sperando che i futuri manutentori leggano il Javadoc e quindi eseguano sempre controlli nulli prima di utilizzare gli argomenti (soluzione 2) :
public int calculateSomething(String p1, BigDecimal p2) {
// my logic
}
In alternativa, potrei sostituire il mio metodo con quattro metodi pubblici per fornire un'interfaccia più gradevole e rendere più ovvio p1 e p2 opzionali (soluzione 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
}
Ora provo a scrivere il codice della classe che invoca questo pezzo di logica per ogni approccio. Richiamo prima i due parametri di input da un altro oggetto che restituisce se Optional
poi invococalculateSomething
. Pertanto, se viene utilizzata la soluzione 1, il codice chiamante sarà simile al seguente:
Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
int result = myObject.calculateSomething(p1, p2);
se viene utilizzata la soluzione 2, il codice chiamante sarà simile al seguente:
Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
int result = myObject.calculateSomething(p1.orElse(null), p2.orElse(null));
se viene applicata la soluzione 3, potrei usare il codice sopra o potrei usare il seguente (ma è significativamente più codice):
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();
}
}
Quindi la mia domanda è: perché è considerata una cattiva pratica usare Optional
s come argomenti del metodo (vedi soluzione 1)? Mi sembra la soluzione più leggibile e rende più evidente che i parametri potrebbero essere vuoti / nulli per i futuri manutentori. (Sono consapevole che i progettisti Optional
intendevano utilizzarlo solo come tipo restituito, ma non riesco a trovare alcun motivo logico per non utilizzarlo in questo scenario).
null
?