Исключения по сравнению со Специальными возвращаемыми значениями

Ну, я нашел решение после глубокого погружения в документацию Apache. Основной заставкой был флаг END (см. https://httpd.apache.org/docs/2.4/rewrite/flags.html#flag_end ) вместе с другими изменениями, которые вы можете найти в конечном результате. .

RewriteEngine On

RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]

RewriteCond %{REQUEST_URI} "api\/.*"
RewriteRule ^api\/(.*)$ server/api.php/$1 [END]

RewriteCond %{REQUEST_URI} !=api\/.*
RewriteRule ^ /index.html [L]

Я надеюсь, что это поможет людям, которые работают с Angular 2+ и хотят использовать один и тот же сервер Apache для бэкэнда и SPA одновременно.

8
задан Joan Venge 23 March 2009 в 20:53
поделиться

15 ответов

Исключением должно быть что-то "исключительное". Таким образом, если Вы звоните, Находят, и Вы ожидаете находить что-то, независимо от того, что, затем выдавая исключение, если Вы не находите, что-то - хорошее поведение.

Если однако это - нормальный поток, что Вы иногда не находите что-то, то выдача исключения плоха.

-1
ответ дан 5 December 2019 в 04:38
поделиться

Ну, ответ - это, зависит.

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

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

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

16
ответ дан 5 December 2019 в 04:38
поделиться

что я обычно делаю в этом случае должен определить класс Опции (вдохновленный F#) и расширить IEnumerable с помощью TryFind () метод, который возвращает класс Опции.

public class Option<T>
{
    string _msg = "";
    T _item;

    public bool IsNone
    {
        get { return _msg != "" ? true : false; }
    }

    public string Msg
    {
        get { return _msg; }
    }

    internal Option(T item)
    {
        this._item = item;
        this._msg = "";
    }

    internal Option(string msg)
    {
        if (String.IsNullOrEmpty(msg))
            throw new ArgumentNullException("msg");

        this._msg = msg;
    }

    internal T Get()
    {
        if (this.IsNone)
            throw new Exception("Cannot call Get on a NONE instance.");

        return this._item;
    }

    public override string ToString()
    {
        if (this.IsNone)
            return String.Format("IsNone : {0}, {1}", this.IsNone, typeof(T).Name);

        else 
            return String.Format("IsNone : {0}, {1}, {2}", this.IsNone, typeof(T).Name, this._item.ToString());
    }

}

Затем можно использовать его как

var optionItem = list.TryFind(x => trueorFalseTest() );
if (!optionItem.IsNone)
   var myItem = optionItem.Get();

Таким образом, существует ли объект или нет, набор, пересечен только однажды.

0
ответ дан 5 December 2019 в 04:38
поделиться

Для первого мне действительно не нравится default(T) опция: что, если Вы имеете int список, где 0 (по-видимому, это intзначение по умолчанию; я не использую C#), совершенно допустимое значение?

(Извинения за синтаксис Java, но если бы я пытался предположить C#, я, вероятно, сделал бы путаницу из него где-нибудь :))

class Maybe<T> {
    public Maybe() {
        set = false;
        value = null;
    }

    public Maybe(T value) {
        set = true;
        this.value = value;
    }

    public T get(T defaultVal) {
        if (set)
            return value;
        return defaultVal;
    }

    private boolean set;
    private T value;
}

Затем, конечно, Find возвратил бы a Maybe<T>, и вызывающая сторона выбирает некоторое значение, это - разумное значение по умолчанию в этом контексте. Возможно, Вы могли добавить getDefault как удобный метод, для когда default(T) правильный ответ, конечно.

Для IndexOf, Тем не менее, -1 разумное значение для этого, так как допустимые значения, очевидно, всегда> = 0, таким образом, я просто сделал бы это.

0
ответ дан 5 December 2019 в 04:38
поделиться

От просто разрабатывают перспективу, я предпочитаю выдавать исключения, когда "исключительная" вещь происходит, например, ключ, который Вы попросили, не был найден. Главная причина состоит в том, что это делает жизнь легче для потребителя - они не должны проверять значение после каждого вызова к Вашей функции. Мне также нравятся функции TrySomething, потому что затем пользователь может явно протестировать, если операция была успешна.

К сожалению, исключения в .NET являются довольно дорогими (на основе моего опыта, обычно требуется приблизительно 50 мс для броска одного), таким образом, с практической точки зрения можно хотеть возвратить одно из этих значений по умолчанию вместо того, чтобы выдать исключение, особенно в программировании GUI.

0
ответ дан 5 December 2019 в 04:38
поделиться

Я думаю, что это является немного ситуационным, но более управляется тем, является ли событие возврата на самом деле логически исключением или нет. indexOf примером является совершенно нормальный выходной ответ, где-1 единственная вещь, которая имеет смысл (или пустой указатель для касательно типов).

Исключение должно быть точно что: исключительный, что означает, Вы хотите всю трассировку стека и обработку, которую можно получить от реального исключения.

0
ответ дан 5 December 2019 в 04:38
поделиться

Более эффективный C# Bill Wagner предоставил превосходную рекомендацию в отношении исключений. Мысль состоит в том, чтобы идти вперед и выдать исключение при выполнении операции просто удостоверьтесь, что Вы обеспечиваете рычаги, чтобы проверить, выдаст ли значение исключение.

Например,

// if this throws an exception
list.GetByName("Frank") // throws NotFound exception
// provide a method to test 
list.TryGetByName("Frank")  // returns false

тем путем можно выбрать из исключения путем записи чего-то как

MyItem item;
if (list.TryGetByName("Frank"))
  item = list.GetByName("Frank");
1
ответ дан 5 December 2019 в 04:38
поделиться

Как во многих проблемах, связанных с программированием всего этого, зависит...

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

Используя Дизайн Контракта может помочь в выполнении этого. Здесь можно было бы вставить функции, которые бросают ошибку или разрушают и указывают на программную ошибку (не пользовательская ошибка). (В некоторых случаях эти проверки удалены в режиме выпуска.)

Затем сохраните Вас исключениями для универсальных отказов, как которые нельзя избежать, соединение с БД отказавшая, оптимистическая отказавшая транзакция, отказавшая запись на диск.

Эти исключения не должны затем обычно должны быть быть пойманы, пока они не достигают 'пользователя'. И приведет к пользователю, чтобы должен попробовать еще раз.

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

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

transferInternal( int account_id_1, int account_id_2, double amount )
{
   // This is an internal function we require the client to provide us with
   // valid arguments only. (No error handling done here.)
   REQUIRE( accountExists( account_id_1 ) ); // Design by contract argument checks.
   REQUIRE( accountExists( account_id_2 ) );
   REQUIRE( balance( account_id_1 ) > amount );
   ... do the actual transfer work
}

string transfer( int account_id_1, int account_id_2, double amount )
{
   DB.start(); // start transaction
   string msg;
   if ( !checkAccount( account_id_1, msg ) ) return msg; // common checking code used from multiple operations.
   if ( !checkAccount( account_id_2, msg ) ) return msg;
   if ( !checkBalance( account_id_1, amount ) ) return msg;
   transferInternal( account_id_1, account_id_2, amount );
   DB.commit(); // This could fail with an exception if someone else changed the balance while this transaction was active. (Very unlikely but possible)
   return "cash transfer ok";
}
1
ответ дан 5 December 2019 в 04:38
поделиться

Который Вы использовали бы?

A:

item = list.Find(x);

B:

If (list.Contains(x))
    item = list.Find(x);
else
    item = null;

C:

try {
   item = list.Find(x);
}
catch {
     item = null;
}

Я готов держать пари, что ответ является A. Поэтому в этом Значении по умолчанию возврата случая (T) является правильным выбором.

3
ответ дан 5 December 2019 в 04:38
поделиться

Лучшие языки позволяют Вам сделать любые соответствия Ваши потребности. Как в Smalltalk-80:

Следующее повысит исключение, если не будет никакого пользователя для идентификатора:

user := userDictionary at: id

Этот оценит данный Блок, который является функцией высокого уровня:

user := userDictionary at: id ifAbsent: [
    "no such id, let's return the user named Anonymous"
    users detect: [ :each | each name = 'Anonymous' ] ]

Обратите внимание на то, что фактический метод является at:ifAbsent:.

2
ответ дан 5 December 2019 в 04:38
поделиться

Можно наслаждаться моим рядом блога с двумя частями, который обсуждает много компромиссов здесь в зависимости от того, какие функции поддержки языка программирования, поскольку это кажется довольно релевантным:

Пример взаимодействия между функциями языка и дизайна библиотеки, части первой

Пример взаимодействия между функциями языка и дизайна библиотеки, части второй

Я добавлю, что думаю, что много ответов на этот вопрос плохо (я downvoted многие мои когорты). Особенно плохо API вроде

if (ItWillSucceed(...)) {
    DoIt(...)
}

которые создают все виды несчастных проблем (см. мой блог для деталей).

3
ответ дан 5 December 2019 в 04:38
поделиться

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

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

3
ответ дан 5 December 2019 в 04:38
поделиться

Эмпирическое правило состоит в том, чтобы использовать исключения только, когда что-то происходит, что "не должен происходить".

Если Вы ожидали бы, что вызов к IndexOf () не мог бы найти рассматриваемое значение (разумное ожидание), то это должно иметь код возврата для того (вероятно-1, как Вы говорите). Что-то, что никогда не должно перестать работать, как выделение памяти, должно выдать исключение в случае возникновения отказов.

Другая вещь помнить, это обрабатывающее исключения "дорого" с точки зрения производительности. Таким образом, если Ваш код регулярно обработает исключения как часть нормального функционирования, то это не будет работать с такой скоростью, как это могло.

6
ответ дан 5 December 2019 в 04:38
поделиться

Я прочитал где-нибудь хорошее правило об этом, что мне нравится очень. Это говорит - "функция, должен выдать исключение, если и только если это не может выполнить задачу, к которой это было предназначено".

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

При разработке приложения хорошо функции будут довольно небольшими и выполнят относительно простые задачи с простыми возвращаемыми значениями. Выбор исключений по вышеупомянутому правилу не будет трудным.

Конечно, всегда существуют неоднозначные случаи (как с ключом, не найденным в словаре). Это должно быть далеким и промежуточным, но там необходимо будет просто использовать инстинктивное чувство на том, что является более изящным решением.

О, и со всем этим никогда не забывайте: чтобы это работало хорошо, хорошее только ловит исключения, которые можно обработать. Главным образом это означает ловлю их только на верхних уровнях UI, где можно отобразиться, пользователю и зарегистрировать их или что-то. Более низкие уровни могли бы использовать finally блоки или исключения переброска после некоторой обработки собственные, но подлинные перехваченные исключительные ситуации на низких уровнях обычно указывают на плохой дизайн.

11
ответ дан 5 December 2019 в 04:38
поделиться

Происходя из среды Java, я предпочитаю исключения в большинстве случаев. Это делает Ваш код намного более чистым, когда половина из него не потрачена, проверив возвращаемые значения.

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

1
ответ дан 5 December 2019 в 04:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: