2010-08-18 5 views
17

Я студент-информатик, поэтому не знаю, что много.Различные стили потока программы?

Я недавно разговаривал с другом, который только что получил работу в качестве разработчика программного обеспечения (Java). Он сказал мне, что на его работе есть парень, который действительно опытен на C++, но, к сожалению, каждый раз, когда он пишет код в java, он использует try-catch для управления потоком программы. По словам моего друга, это неправильный стиль в Java. Это правда? Каковы различия (если они есть) при использовании try-catch (-finally в java) между C++ и Java?

+1

+1 ответ Джона Уэлдона. Обратите внимание, что одним из очень неприятных аспектов части экосистемы Java (и которая является спецификацией Java) является чрезмерное использование ** проверенных ** исключений некоторыми API/фреймами. В основном, заставить пользователей API контролировать поток своей программы, улавливая бессмысленное исключение без проверки для вещей, которые не являются исключительными вообще. Некоторые рамки, такие как Spring, правильно спроектированы и действительно недовольны этой ужасно плохой практикой. Джошуа Блох в своей «Эффективной Java» рекомендует предпочесть «метод тестирования состояния» для ненужного исключения (исключений) проверенных исключений. – NoozNooz42

+0

Привет Спасибо за ответ. «В основном, заставить пользователей API контролировать поток своей программы, улавливая бессмысленное исключение без проверки для вещей, которые не являются исключительными вообще». Итак, в чем разница между попытками между C++/Java? Кроме того, что вы имеете в виду «проверенные» исключения? Cheers – Muggen

+1

См. Http://www.javapractices.com/topic/TopicAction.do?Id=129. Проверенные исключения по сути являются злоупотреблением исключениями для не исключительного контроля потока. Они также являются кошмаром для обслуживания. –

ответ

28

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

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

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

Например, контролирующей поток программы в псевдокоде:

try { 
    write update to file 
} catch (IOException) { 
    write update to alternate file 
} 

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

Я удалил разрешение проверки заметок, потому что это плохой пример

Хорошее использование обработки исключений: (псевдо-код еще раз)

try { 
    do stuff 
} catch(OutOfMemoryException) { 
    fail gracefully (don't try and do something else to achieve the same result) 
} 
+1

Привет. Спасибо за ответ. Было бы возможно показать некоторый код, в котором контрольный поток контролирует поток, и аналогичный случай, когда это не так? Спасибо – Muggen

+2

Это действительно хороший вопрос @Muggen; Я дам ему шанс обновить свой ответ, но я думаю, что стоит вопрос о его собственном. –

+3

@Muggen, если у вас есть открытый файл, который вы должны прочитать, но если вы не можете это сделать, исключительный случай. Если пользователь пытается войти в систему, но вводит неверный пароль, это нормальное состояние потока, и его следует обрабатывать следующим образом, а не с помощью try-catch –

-2

Ваш вопрос является слишком расплывчатым без образца кода. В C++ нет finally.

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

+1

На самом деле этот ответ начинает рассматривать «другой» вопрос, который поставил ОП: Каковы различия в обработке исключений между java и C++ –

+0

Это хороший ответ, +1. – fastcodejava

8

Я бы сказал, что с точки зрения архитектуры программного обеспечения цель исключений одинакова в Java и C++. Они должны использоваться для обработки исключительных случаев, а не для прямого нормального потока программы.

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

+0

Привет. «... особенно если исключения используются правильно». Как исключение можно использовать ненадлежащим образом? – Muggen

+2

Всякий раз, когда он используется для управления потоком программы, а не для обработки исключительных случаев. Например, если вы можете проверить длину массива, не используйте исключение index out of bounds, чтобы знать, что вы передали длину массива для индекса, но вместо этого просто завершите цикл for в соответствующей точке. – aperkins

+3

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

4

Я бы ожидать, что C++ и Java миров, чтобы быть во многом схожи в своих взглядах:

  1. управления потоком с Try/уловом блоками не сразу виден
  2. это дорого производительность мудрым. На практике это может не быть проблемой, но во многих сценариях (например, жестких петлях) это, безусловно, повлияет на вас.
6

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

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

Вместо этого вы должны использовать утверждения, такие как break, return или даже (в реальном случае). goto.

+2

С другой стороны, это «да-да» в Python, где ** каждый для цикла ** завершается обработкой исключения StopIteration. ;) – UncleBens

+2

@UncleBens - Большое вам спасибо за то, что вы подтвердили мое желание. Я подумал, что там должно быть хотя бы одно. :-) –

2

Блок try-catch предназначен для того, чтобы делать то же самое на всех языках - исключения - один из многих способов восстановления, когда что-то идет не так. В Java, следующие два оператора идентичны:

if(x != null){ 
    //do the normal thing 
} 
else{ 
    //recover from the error 
} 

и

try{ 
    //do the normal thing 
} 
catch(NullPointerException ex){ 
    //recover 
} 

Однако использование исключений не бывает хорошей идеей по ряду причин:

  • затраты, связанные с бросанием исключение (т. е. генерирование Throwable в Java)
  • поток управления не сразу становится очевидным - например, если исключение NullPointerException может быть брошенной нескольких операторов в блоке попробовать, как вы можете сказать, один бросил его в блок поймать
  • и т.д., и т.д.
+0

Привет. Спасибо за ответ. «как вы можете сказать, кто бросил его в блок catch», это еще один вопрос, который у меня был. Значит, вы почти уверены в том, что try-catch следует использовать только в особых случаях или я понял неправильно? Cheers – Muggen

+0

Будьте осторожны, сказав, что эти конструкции идентичны или эквивалентны. Если «// делать обычную вещь» сначала делает что-то, что неправильно использует ссылку «null», то второй пример будет выполнять некоторую работу (возможно, с видимыми побочными эффектами), которая не встречается в первом примере. –

+0

Подождите, это «никогда» хорошая идея ?! Исключения идеальны для того, для чего они предназначены: исключения. В отличие от результирующих кодов, их нельзя игнорировать, и они автоматически выходят из строя, пока не найдут код, который готов обработать их. Никогда не говорите никогда, особенно о вещах с четко определенным использованием. –

3

единственным целью try/catch является управление потоком. Он предназначен для того, чтобы позволить нам выйти из любого цикла и даже пройти мимо вызывающего абонента и до функции более высокого уровня.

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

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

Когда люди жалуются, используя try/catch для управления потоком, что они должны в виду, что это не для контроля потока в неисключительных условиях. Если все, что вы хотите сделать, это выйти из цикла, используйте break или return; не бросайте исключение, а затем ловите его. Это не то, за что нужны исключения, и не то, для чего они хороши.

+0

Хорошее объяснение @Steven. Я не уверен, что это стоило уменьшить мой ответ, но, тем не менее, хорошо :) –

+0

@John: У вас есть 20 upvotes. люди останавливаются и смотрят на альтернативы. –

1

То, что он может хотеть есть несколько способов, чтобы не выполнить немного кода ... так, а не (в Java)

if (cond1) { 
    some_code(); 
    if (cond2) { 
    some_more_code(); 
    if (condN) { 
     ad_infinitum 
    } 
    } 
} 

Это может быть «сплющенные», бросая какую-то фигню ...

try { 
    if (!cond1) throw new Throwable(); 
    some_code(); 
    if (!cond2) throw new Throwable(); 
    some_more_code(); 
    if (!condN) throw new Throwable(); 
    ad_infinitum(); 
} catch (Throwable ignore) { } 

Проблема в том, что если какое-то реальное исключение было брошено?Я думаю, что ваш коллега должен писать, если он хочет, чтобы сгладить отступы что-то вроде этого:

do { 
    if (!cond1) break; 
    some_code(); 
    if (!cond2) break; 
    some_more_code(); 
    if (!condN) break; 
    ad_infinitum(); 
} while (false); 

Поскольку делать/в то время как всегда выполняется, мы можем использовать перерыв, чтобы приблизить Гото (до тех пор, как все это идет в одно и то же место).

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