Является ли наличие двух версий одного и того же метода, которые отличаются только по сигнатуре (имя метода и атрибут «throws»), плохим дизайном? - PullRequest
4 голосов
/ 25 мая 2019

Я хотел бы разработать API, в котором у меня есть две версии одного и того же метода, extractLastElement():

  1. Первая версия не будет иметь атрибут throws: Object extractLastElementSafe(); Будетиспользуется, когда клиент 'точно знает' , что есть элементы внутри коллекции, например, он только что добавил некоторые элементы, поэтому нет необходимости в шаблонном коде try-catch.

  2. Вторая версия выдаст Проверенное исключение: Object extractLastElement() throws NoMoreElementsException;Будет использоваться клиентом, когда он не уверен, остались ли еще элементы в коллекции, например, внутри цикла.

Это считается плохим дизайном?Есть ли альтернатива для подражания этому поведению?

public class SomeCollection {

  private List<String> arr;

  public SomeCollection(List<String> arr) {
      this.arr = arr;
  }

  public String extractLastElementSafe() {
      return arr.remove(arr.size() - 1);
  }

  public String extractLastElement() throws NoElementsLeftException {
      try {
          return arr.remove(arr.size() - 1);
      } catch (IndexOutOfBoundsException e) {
          throw new NoElementsLeftException(e); // throwing a checked exception
      }
  }
}

class NoElementsLeftException extends Exception {
  public NoElementsLeftException(Throwable cause) {
      super(cause);
  }
}

Ответы [ 2 ]

4 голосов
/ 25 мая 2019

Всегда сомнительно, чтобы пользователи могли делать одно и то же по-разному. Также не элегантно заставлять клиента беспокоиться о том, есть ли последний элемент или нет.

Но, в конце концов, это скорее стиль, и ваш подход можно рассматривать как нормальный. Тем не менее вы предоставляете своим клиентам возможность вызывать «безопасный» метод и в итоге получить исключение времени выполнения. Таким образом, на самом деле есть два разных сценария ошибок.

Одна тонкая вещь, которую определенно нужно изменить: избегайте дублирования кода! Метод, который делает try / catch для выброса этого исключения, должен просто вызвать «безопасный» метод!

Сказав все это, я лично предложил бы только один метод, который выдает какое-то исключение во время выполнения. Стандартные коллекции Java используют непроверенные исключения, как и вы.

Цитируя Роберта Мартина: «Война между проверенными и непроверенными исключениями окончена, и непроверенная победа». И он написал это более 10 лет назад.

1 голос
/ 04 июня 2019

Если у вас есть четко определенные сценарии использования для каждой версии метода, имеет смысл использовать оба варианта.Пример такого проектного решения можно найти в классе Queue , который работает в двух режимах, например, при попытке удалить элемент из пустой очереди: один метод (poll) возвращает ноль, а другой(remove) выдает исключение.

...