Przeczytałem na wielu stronach internetowych Opcjonalne powinny być używane tylko jako typ zwracany, a nie używane w argumentach metod. Próbuję znaleźć logiczny powód. Na przykład mam logikę, która ma 2 opcjonalne parametry. Dlatego myślę, że sensowne byłoby napisanie mojej sygnatury metody w ten sposób (rozwiązanie 1):
public int calculateSomething(Optional<String> p1, Optional<BigDecimal> p2 {
// my logic
}
Wiele stron internetowych określa Opcjonalne nie należy używać jako argumentów metody. Mając to na uwadze, mógłbym użyć poniższej sygnatury metody i dodać wyraźny komentarz Javadoc, aby określić, że argumenty mogą być zerowe, mając nadzieję, że przyszli opiekunowie przeczytają Javadoc, a zatem zawsze przeprowadzają kontrole zerowe przed użyciem argumentów (rozwiązanie 2) :
public int calculateSomething(String p1, BigDecimal p2) {
// my logic
}
Alternatywnie mógłbym zastąpić moją metodę czterema publicznymi metodami, aby zapewnić lepszy interfejs i uczynić go bardziej oczywistym, p1 i p2 są opcjonalne (rozwiązanie 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
}
Teraz próbuję napisać kod klasy, który wywołuje tę logikę dla każdego podejścia. Najpierw pobieram dwa parametry wejściowe z innego obiektu, który zwraca Optional
s, a następnie wywołuję calculateSomething
. Dlatego jeśli zastosowane zostanie rozwiązanie 1, kod wywołujący wyglądałby następująco:
Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
int result = myObject.calculateSomething(p1, p2);
w przypadku użycia rozwiązania 2 kod wywołujący wyglądałby następująco:
Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
int result = myObject.calculateSomething(p1.orElse(null), p2.orElse(null));
jeśli zastosowane zostanie rozwiązanie 3, mógłbym użyć powyższego kodu lub użyć następującego (ale jest to znacznie więcej kodu):
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();
}
}
Więc moje pytanie brzmi: dlaczego uważa się za złą praktykę stosowanie Optional
s jako argumentów metody (patrz rozwiązanie 1)? Wydaje mi się to najbardziej czytelnym rozwiązaniem i sprawia, że przyszłym opiekunom staje się oczywiste, że parametry mogą być puste / zerowe. (Wiem, że projektanci Optional
zamierzali go używać tylko jako typ zwrotu, ale nie mogę znaleźć żadnych logicznych powodów, aby nie używać go w tym scenariuszu).
null
?