Jump to content
  • 0

когда использовать try/catch ?


cyklop77
 Share

Question

...а я продолжаю серию смешных вопросов по основам. но для меня они действиетльно важные, поэтому пожалуйста поделитесь опытом и не смейтесь

 

всегда хотелось разобраться толком с назначением конструкций типа try/catch. в зависимсоти от языка названия могут различаться, но смысл остаётся. а смысл по-моему лишь в том, чтобы проверить множественное действие. то есть try/catch стоит использовать только тогда, когда конструкции типа if недостаточно. прав ли я?

 

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

1. многострочные:

try  post = Post.new  post.title = 'good post' + $postfix  post.body = file.open(/folder/file.txt)  post.savecatch(nameError)  modal_window_with_errormessage_raise()catch(nameError)  bla_bla()catch(nameError)  bla_bla()catch(nameError)  bla_bla()catch(nameError)  bla_bla()finally  bla_bla_final()end

2. однострочные

try  file.open(/db_temp/data.xml)catch(nameError)  modal_window_with_errormessage_raise()catch(nameError)  bla_bla()catch(nameError)  bla_bla()catch(nameError)  bla_bla()catch(nameError)  bla_bla()finally  bla_bla_final()end

в первом случае ошибка может произойти например в строке:

  • post.title = 'good post' + $postfix , если невозможно произвести конкатенацию из-за несовпадения типов
  • post.body = file.open(/folder/file.txt) , если нет прав на файл
  • post.save , если БД занята в данный момент

во втором случае в единственной строке может произойти ошибка потому что:

  • нет прав на доступ к файлу,
  • физически нет файла на HDD,
  • в файл в данный момент пишутся данные

 

то есть try/catch использовать разумно только в перечисленных случаях, иначе программе добавляется неоправданная сложность. прав ли я или еть ещё случаи, в которых применяется try/catch?

 

ps:

короче у меня в голове каша, но хотелось бы разобраться

Link to comment
Share on other sites

3 answers to this question

Recommended Posts

  • 0
а я продолжаю серию смешных вопросов

ну не такой уж и смешной вопрос)) я их практически не использую =)

 

 

 

прав ли я или еть ещё случаи, в которых применяется try/catch?

замечал может быть в консоли у многих фреймворков, библиотек, плагинов (js) или же у большинства CMS (php) есть свой вывод ошибок?

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

  • Like 1
Link to comment
Share on other sites

  • 0
попытаюсь предоставить наглядный практический пример к тому, что я написал выше. вот реальная задача на ruby on rails. я буду очень подробно пояснять ход программы чтобы не привязывать задачу к конкретному языку/фреймворку

 

есть блог с системой тегов. пользователь имеет возможность редактировать посты и при этом менять привязанные к посту теги, удалять и создавать новые. на уровне модели теги и посты связаны связью многие ко многим(has and belongs to many). на уровне БД табличка post связана с табличкой tags через табличку post_tags, которая состоит из двух колонк: tags(integer), posts(integer)

 

вот экшн update, который срабатывает после того как пользователь ввёл нужные изменения и отправил форму. 

вариант1:



def update
if @post.update(post_params)
add_new_tags(@post) if params[:tagnames] # если из формы пришли новые теги, то добавляем их в табличку tags и создаём ассоциации в табличке post_tags
destroy_tags(params['delete_tags'], @post) if params['delete_tags'] # если из формы пришёл список тегов для удаления, то удаляем соответствующие ассоциации
redirect_to user_post_path(current_user.id, @post.id), notice: 'posts was successfully updated.' # редирект куда-то там, в случае успешного обновления поста
else
render :edit # тоже типа редиректа, только в другое место
end
end

def add_new_tags(post)
tagnames = params[:tagnames].split(/[, \.?!]+/) # разбиваем строку по запятым и получаем набор тегов
tagnames.each do |tagname| # цикл по тегам
tag = Tag.find_by(title: tagname.downcase) # ищем в табличке tags существующий тег
if tag
# если находим уже существующий тег, то.....
sql = "select * from 'posts_tags' where post_id = #{post.id} and tag_id = #{tag.id}"
records_array = ActiveRecord::Base.connection.execute(sql) # ...... проверяем есть ли ассоциация в табличке post_tags
tag.posts << post if records_array.count == 0 # ...............если её нет, то создаём
else
# если не находим существующий теги, то............
tag = Tag.create(title: tagname.downcase) # .............создаём его
tag.posts << post # .........и добавляем ассоциацию
end
end
end

def destroy_tags(tags,post)
tags.each do |tag| # цикл по тегам
sql = "delete from 'posts_tags' where post_id = #{post.id} and tag_id = #{tag}"
records_array = ActiveRecord::Base.connection.execute(sql) # удаляем ассоциацию
end
end


 

 

вариант2:



def update
begin
@post.update(post_params)
add_new_tags(@post) if params[:tagnames]
destroy_tags(params['delete_tags'], @post) if params['delete_tags']
redirect_to user_post_path(current_user.id, @post.id), notice: 'posts was successfully updated.'
rescue
logger.debug 'update post is failed' # запись в лог
render :edit
end
end

def add_new_tags(post)
tagnames = params[:tagnames].split(/[, \.?!]+/)
tagnames.each do |tagname|
tag = Tag.find_by(title: tagname.downcase)
if tag
sql = "select * from 'posts_tags' where post_id = #{post.id} and tag_id = #{tag.id}"

begin
records_array = ActiveRecord::Base.connection.execute(sql)
tag.posts << post if records_array.count == 0
rescue
logger.debug 'query for add association posts_tags is failed'
raise 'add_new_tags error'
end
else
begin
tag = Tag.create(title: tagname.downcase)
tag.posts << post
rescue
logger.debug 'query for create tag and add association posts_tags is failed'
raise 'add_new_tags error'
end
end
end
end

def destroy_tags(tags,post)
tags.each do |tag|
sql = "delete from 'posts_tags' where post_id = #{post.id} and tag_id = #{tag}"

unless ActiveRecord::Base.connection.execute(sql)
logger.debug 'query for delete tags is failed'
raise 'destroy_tags error'
end
end
end



 

вопрос. во втором варианте оправдана ли дополнительная сложность в виде добавленных проверок типа begin/rescue. от этих проверок стал ли код более защищённым от ошибок. так вообще правильно программировать?

Edited by cyklop77
Link to comment
Share on other sites

  • 0

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

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

 

например 
 

         sql = "select * from 'posts_tags' where post_id = #{post.id} and tag_id = #{tag.id}"      begin        records_array = ActiveRecord::Base.connection.execute(sql)             tag.posts << post if records_array.count == 0      rescue        logger.debug 'query for add association posts_tags is failed'        raise 'add_new_tags error'      end

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

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

  • Like 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. See more about our Guidelines and Privacy Policy