#java #optional #misuse
#java #необязательно #неправильное использование
Вопрос:
Мне просто интересно, является ли следующее неправильным вариантом использования Optional. Вероятно, так и есть, потому что это выглядит неприятно.
(Речь идет о вызове «устаревшего» кода, который возвращает нули.)
private static class Person {
private Address address;
private String name;
}
private static class Address {
private Integer housenr;
private String houseletter;
private String street;
}
public String getAddress(Person person) {
return Optional.ofNullable(person.getAddress())
.map(x -> Optional.ofNullable(x.getHousenr()).map(y -> y " ").orElse("")
Optional.ofNullable(x.getHouseletter()).map(y -> y " ").orElse("")
Optional.ofNullable(x.getStreet()).orElse(""))
.orElse("<unknown>");
}
// unit test if string representation of an address is properly generated
assertThat(getAddress(charlesBabbage))
.isEqualTo("4 l Regentstreet");
Вероятно, мне следует поместить код в метод класса Person и класса Address, чтобы меня это не так сильно беспокоило.
Или я должен сделать это «по-старому»:
public String getAddress(Person person) {
if (person.getAddress() == null) {
return "<unknown>";
}
StringBuilder builder = new StringBuilder();
if (person.getAddress().getHousenr() != null) {
builder.append(person.getAddress().getHousenr() " ");
}
if (person.getAddress().getHouseletter() != null) {
builder.append(person.getAddress().getHouseletter() " ");
}
if (person.getAddress().getStreet() != null) {
builder.append(person.getAddress().getStreet() " ");
}
return builder.toString();
}
Имейте в виду, что это всего лишь пример. Можно добавить дополнительные поля, такие как affix., почтовый ящик, город / город, муниципалитет, штат, страна (не говоря уже об иностранных адресах), что усугубляет проблему.
Комментарии:
1. это нечитаемо, просто укажите поля по отдельности
2. Извините, @Andrew Tobliko. Прояснил цель кода.
3. оба выглядят плохо для меня, зачем вам нужно создавать строку? макет «4 l Regentstreet» в качестве объекта адреса и сравнение 2 объектов
4. Мне нужно создать строку, чтобы представить ее пользователю.
Ответ №1:
В обоих ваших примерах вы повторяете код, который проверяет, что элементы не являются нулевыми, прежде чем добавлять их в строку. Вы можете уменьшить эту повторяющуюся работу, используя Stream и joining:
public String getAddress(Person person) {
return Optional.ofNullable(person.getAddress())
.map(x -> Stream.of(x.getHousenr(), x.getHouseletter(), x.getStreet())
.filter(Objects::nonNull)
.map(Object::toString)
.collect(Collectors.joining(" "))
)
.orElse("<unknown>");
}
Или аналогично без Optional:
public String getAddress(Person person) {
Address address = person.getAddress();
if (address == null) {
return "<unknown>";
}
return Stream.of(address.getHousenr(), address.getHouseletter(), address.getStreet())
.filter(Objects::nonNull)
.map(Object::toString)
.collect(Collectors.joining(" "))
}
Ответ №2:
Я вообще не считаю, что это неправильный вариант использования. Правда, это не так просто читать, не думая о форматировании и пробелах, но способ, который вы используете Optional
, кажется мне прекрасным.
Ради утверждения хорошо иметь этот (действительно уродливый) код. Я не знаю вашего окончательного предполагаемого варианта использования, но предполагая, что вы просто хотите сгенерировать строковые представления этих объектов, я бы инкапсулировал логику, которая проверяет наличие нулей в соответствующих классах, в toString()
метод или аналогичный.
редактировать: неприятный вид кода не делает его использование неправильным. Хотя ваши коллеги могут в конечном итоге возненавидеть вас
Комментарии:
1. Хотя рабочий код важен, неприятный код, скорее всего, неоправданно увеличит затраты на обслуживание, и это тоже очень важно…. ЧАСТО это важнее, чем «рабочий» код; особенно если ожидаемая продолжительность жизни системы составляет годы. ВСЕГДА переосмысливайте свою стратегию, если интуиция подсказывает вам, что код уродлив или нечитаем.