Подтвердить что ты не робот

Это хорошая или плохая идея, бросающая Исключения при проверке данных?

При проверке данных у меня появилась привычка делать следующее:

Примечание. У меня нет отдельных логических значений для каждой проверки. Это только для примера.

Еще одно примечание: любая обработка ошибок во время тестов выполняется правильно. ЕДИНСТВЕННЫЕ исключения, добавленные в try-catch, - мои собственные.

try {
  if (validCheckOne = false) {
    throw new Exception("Check one is bad");
  }
  if (validCheckTwo = false) {
    throw new Exception("Failed because of check2");
  }
  if(validCheckTen = false) {
    throw new Exception("Yet another failure on your part: check10.");
  }
} catch(Exception e) {
  MessageBox.Show("Your stupid data is wrong! See for yourself: " + e.Message);
}

Это плохая практика? Вызывает ли исключение замедление выполнения программы или нецелесообразно?

4b9b3361

Ответ 1

Лично мне нравится бросать исключения для проверки бизнес-правил (не столько для проверки правильности ввода данных), сколько заставляет проблему обрабатывать вверх по потоку. Если мои бизнес-объекты вернули какой-то результат проверки, он может быть проигнорирован вызывающим. Назовите меня ковбой, если хотите:)

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

Ответ 2

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

Ответ 3

Я поддерживаю ответ MusiGenesis.

Дополнительно...


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

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

Ответ 4

В дополнение к часто повторяемому утверждению, что "исключения относятся к исключительным обстоятельствам", здесь дополнительно разъясняющее правило, которое мне пришло в голову:

Если пользователь вызвал это, он не является исключительным.

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

Ответ 5

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

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

Ответ 6

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

Ответ 7

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

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

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

Ответ 8

Это плохое поведение. Исключения для исключительных условий. Они берут ресурсы для создания стека и т.д. Исключения не должны использоваться, чтобы диктовать поток процесса.

Ответ 9

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

  error = false;
  while(true) {
    if(validCheckOne == false) { 
       msg = "Check one is bad"; 
       error = true;
       break;
    }

    if(validCheckTwo == false) { 
       msg = "Check two is bad"; 
       error = true;
       break;
    }
    ...
    break;
  }
  if (error) {
     ..
  }

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

Ответ 10

Я вообще согласен с тем, что правило исключений должно быть исключительным, но я могу сделать исключение (ha!) для Python, где он может быть эффективным и считается хорошей практикой использования try... кроме управления потоком.

См. Использование исключений для других целей.

Ответ 11

Я бы предположил, что использование исключений, описанных в вопросе (для управления потоком внутри функции), является wrong, как правило, не лучшая идея. Я бы пошел дальше и сказал, что исключения для исключения валидации - это не лучший подход; вместо этого возвратите логическое значение и сохраните список сообщений об ошибках проверки, к которым можно получить доступ. Сопровождающий метод save может/должен генерировать исключение, если он вызван на недопустимый объект.

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

Другая потенциальная проблема с вашим примером кода (в зависимости от требований, конечно) заключается в том, что она вызывает только первую ошибку проверки. Представьте себе это от пользователей POV:

  • Нажмите "Сохранить"
  • Получить сообщение об ошибке
  • Правильная ошибка
  • Нажмите "Сохранить снова"
  • Получить другое сообщение об ошибке. Раздражает.

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

Ответ 12

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

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

private void throwIf( bool condition, String message )
{
    if( condition )
        throw new ApplicationException( message );
}

(также, это поможет обнулить ошибки, такие как "validCheckOne = false" и "validCheckOne == false":)

Ответ 13

Этот вопрос все еще интересен, в основном из-за ответов.

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

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

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

Например, при работе с пользовательским вводом может произойти много странных случаев. Вставленные данные с веб-сайта, заполненного скрытыми символами (\ t\n и т.д.), Опечатками и действительно огромным количеством случаев, когда конкретное исключение может позволить более точный анализ или сообщение для использования гораздо точнее, чем простой "ложный" возврат ,

Ответ 14

Ну, я знаю это старый вопрос. Но я позволю свое мнение здесь для Google, который упал здесь, как я:

  1. Если вы используете язык с плохой поддержкой try/catch AVOID БРОСЕНИЕ исключений для проверки данных;
  2. НЕ БРОСАЙТЕ исключение, которое не будет обработано вызывающей стороной или alserwhere;
  3. НЕ БРОСАЙТЕ исключение, если вам необходимо проверить остальные полученные данные;
  4. Вы можете THROW сделать исключение в тех случаях, когда блок кода не может продолжаться без неверных данных; И если вы не прервете процесс, вы может получить необработанное исключение;

Пример:

/*
 * Here it a common problem i have: Someone pass a list of products i need to
 * retrieve from the database and update some information;
 */

//This is a class to represent the product
function Product(id, name, price) {
	this.id = id;
	this.name = name;
	this.price = price;
}

//This is an example function to retrieve the product from the database
function findProductInDatabase(productId) {

	//If the product exists on the database, the function will return it
	if (productId == 12) {
		var product = new Product(12, "Book", 20.5);
		return product;
	}
	
	//If the product do not exists, it will return null
	return null;
}

//This is a function that will receive the productID and will update the received parameters
function updateProduct(productId, newProductName, newProductPrice) {

	var productFromDatabase = null;
	var errorMessage = "";
	
	//Retrieve the product
	productFromDatabase = findProductInDatabase(productId);

	//If the product do not exist, i need to interrupt de method imediatily and alert the caller
	if (!productFromDatabase) {
		throw "Product not found";
	}
	
	//Validate the other parameters, but in this case	i can validate all the parameters
	if (newProductPrice < 10) {
		errorMessage += "the price is too low";
	}
	
	if (newProductName.includes("<")) {
		
		//If already has a error message in the variable i append " and " to the message make sense
		if (errorMessage) {
			errorMessage += " and ";
		}
		
		errorMessage += "the new name has invalid characters";
	}
	
	if (errorMessage) {
		//if theres any error, i will throw a exception with the messages
		throw errorMessage;
	}
}

//This parte is where the method id called;
try {
	updateProduct(9, "Book", 10.5);
} catch (exception) {
	console.log("Case 1: " + exception);
}
try {
	updateProduct(12, "<Book", 9);
} catch (exception) {
	console.log("Case 2: " + exception);
}