2015-04-21 2 views
4

Я смущен о том, что считается хорошей практикой, зависит ли это от решения? Предположим, у меня есть следующий код Java:Возврат дефолта или рейза Исключение?

public class Stack { 
    public Integer pop() { 
    if (isEmpty()) return null; // or some exception maybe? 
    // else get and return the top item in the stack. 
    }; 
} 

Клиент метода pop ожидает некоторое Integer значение так, что будет самым лучшим подходом, чтобы позволить клиенту знать, что стек пуст?

+1

Я думаю, что это действительно зависит от того, чего вы хотите достичь. В любой ситуации спросите себя: Ожидается ли, что мой API возвращает значение по умолчанию? Должен ли пользователь моего API знать, что это значение по умолчанию? В большинстве случаев доступ или манипулирование данными/памятью должны бросать исключения, если что-то пошло не так. Но для понятий, которые вы создали, это зависит от вас. – Tonio

+0

Хорошим примером этого является математика. Некоторое неопределенное поведение устанавливается по соглашению (например, 0 до 0-й степени равно 1 или 0! Равно 1), а некоторые не определены (например, деление на 0 или неопределенные формы для лимитов). Первая категория возвращает значения по умолчанию, в то время как последняя генерирует исключения. – Tonio

ответ

2

Возвращаемое значение null или значение по умолчанию обычно Неправильная практика и исключение должно быть предпочтительным. Причина в том, что вы всегда должны стремиться к сбою так быстро, как можете,, когда что-то пойдет не так. Если вы вернете null - вы получите ошибки, происходящие в каком-то другом месте в коде, и пользователи вашего API будут иметь проблемы с обнаружением проблемы. Это называется Fail Fast

Исключением из этого правила является то, что ваш API заставит пользователей полагаться на исключения для управления потоком, поэтому, если ваш стек не поддерживает isEmpty(), исключение здесь не очень хорошо.
Если у вас есть стек, который может позволить только peek(), pop() и add() - по какой-то причине isEmpty() не может быть частью API.

Что произойдет с кодом ваших пользователей для обоих подходов?

вариант 1 - с помощью нуля:

Integer x = stack.pop(); 
if (x != null) { 
    //do something with x 
} 

Вариант 2 - с использованием исключений:

Integer x = null; 
try { 
    x = stack.pop(); 
} catch (MyException e) { } 
//do something with x 

Вторым фактически используют механизм исключений для управления потоком - который является большим недостатком в дизайне API ,

+0

Можете ли вы объяснить свой второй пункт? – CodeYogi

+0

@CodeYogi добавлен больше информация об этом. – amit

+0

Итак, вы в основном говорите, что «Исключения» хороши для внутреннего использования, но не для API, предназначенных для использования внешними клиентами, не так ли? – CodeYogi

2

Вы можете выбросить IllegalStateException.

Сигналы о том, что метод был вызван в незаконное или ненадлежащее время.

Вызов pop() на пустой стек - это вызов в неподходящее время.

Более современный подход бы вернуть Optional<Integer>, который является рекомендуемым способом в Java 8, avoud null возвращается.

public class Stack { 
    public Optional<Integer> pop() { 
    if (isEmpty()) return Option.ofNullable(null); 
    return Optional.of(valueOnTheStack); 
    } 
} 
0

В соответствии с Java API, пытаясь выскочить элемент из пустого стека должен выход исключение.

Таким образом, я думаю, что в вашем случае вы должны сделать то же самое (предполагая, что вы реализуете это на Java). Другие языки могут иметь дело с этим по-другому, хотя.

+0

Вы указываете на конкретную реализацию языка так, вы имеете в виду, что это зависит от конкретного языка? – CodeYogi

+0

@CodeYogi: Я попытался придумать практический пример вашей проблемы, особенно учитывая, что ваш код находится на Java. В C# у вас может быть метод 'bool TryGet (int index, out T value)', который будет возвращать 'false', если элемент не существует, вместо того, чтобы выбрасывать исключение. (** Важно ** Теперь я знаю, действительно ли этот метод существует на C#, но я думаю, что он должен передать точку). – npinti

+0

Ваши аргументы в пользу [обращения к авторитетной логической ошибке] (https://yourlogicalfallacyis.com/appeal-to-authority) того факта, что java не является причиной сама по себе, почему это должно быть сделано. – amit

0

В случае создания API он должен быть абстрактным и использовать Исключения, поскольку он будет интегрирован в Java-среду, тогда поп-операция будет выглядеть следующим образом.

public Integer pop() throws Exception 
{ 
    if (stack.isEmpty()) 
     throw new java.util.EmptyStackException(); 

    return stack.pop(); 
} 

Если я создаю это как веб-службы, то я хотел бы сделать это следующим образом. В основном, чтобы убедиться, что стандартизация различных типов внутренних исключений представлена ​​через возвращаемый объект использования стека.

StackService

@WebService 
class MyStack 
{ 
    StackProvider provider; 
    Stack stack; 

    public MyStack (StackProvider provider) 
    { 
     this.provider = provider; 
     this.stack = provider.readStack(); 
    } 

    public void sync() 
    { 
     provider.syncStack(stack); 
    } 

    public Integer pop() 
    { 
     if (stack.isEmpty()) 
      return new StackElement(StackElement.STACK_EMPTY); 

     return new StackElement(stack.pop()); 
    } 

    public void push (Integer val) 
    { 
     stack.push(val); 
    } 
} 

StackElement

class StackElement 
{ 
    public static final char STACK_EMPTY = 0; 
    public static final char ELEMENT_VALID = 1; 

    public Integer value; 
    public char flag; 

    public StackElement (Integer val) 
    { 
     this.value = val; 
     this.flag = StackElement.ELEMENT_VALID; 
    } 

    public StackElement (char flag) 
    { 
     this.value = null; 
     this.flag = flag; 
    } 

    public boolean isValid() 
    { 
     return (flag == 1); 
    } 
} 

Тест

class Test 
{ 
    public static void main (String [] args) 
    { 
     StackProvider provider = new StackProvider("..."); 

     // init 

     MyStackService service = new MyStackService(provide); 
     MyStackServiceSoap soap = service.getMyStackServiceSoap(); 

     // call pop operation 

     StackElement element = soap.pop(); 

     // checking the value 

     if (element.isValid()) 
      System.out.println("Stack.Pop ~ " + element.value); 
     else 
     { 
      if (element.flag == StackElement.STACK_EMPTY) 
      System.out.println("Stack is Empty"); 
      else 
      System.out.println("Unknown error"); 
     } 

    } 
} 
Смежные вопросы