Когда использовать блоки - PullRequest
23 голосов
/ 02 февраля 2010

Мне нравятся блоки Ruby! Идея, лежащая в их основе, очень, очень аккуратная и удобная.

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

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

something.do_stuff do |status|
  status.success do 
    # successful code
  end

  status.fail do
    # fail code
    puts status.error_message
  end
end

Я использую блоки слишком много?Есть ли время для использования блоков и время для использования возвращаемых значений?

Есть ли какие-то ошибки, о которых нужно знать?Придет ли когда-нибудь мое огромное использование блоков и укусит меня?

Ответы [ 3 ]

16 голосов
/ 02 февраля 2010

Все это было бы более читабельно, как:

if something.do_stuff
  #successful code
else
  #unsuccessful code
end

или использовать обычную идиому рельсов:

if @user.save
  render :action=>:show
else
   @user.errors.each{|attr,msg| logger.info "#{attr} - #{msg}" }
   render :action=>:edit
end

ИМХО, избегание возврата логического значения - это чрезмерное использование блоков кода.

Блок имеет смысл, если. , .

Позволяет коду использовать ресурс, не закрывая его

 open("fname") do |f|
  # do stuff with the file
 end #don't have to worry about closing the file

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

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

something.do_stuff do |res1, res2|
   if res1.foo? and res2.bar?
      foo(res1)
   elsif res2.bar?
      bar(res2)
   end
 end #didn't add res1/res2 to the calling scope

Код должен вызываться как до, так и после выхода

Вы видите это в некоторых помощниках рельсов:

 &lt% content_tag :div do  %>
     &lt%= content_tag :span "span content" %>
  &lt% end -%>

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

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

13 голосов
/ 02 февраля 2010

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

5 голосов
/ 02 февраля 2010

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

Возвращать значения имеет смысл, когда возвращаемые значения имеют смысл. Если у вас есть объект Article, вы хотите, чтобы article.title вернул заголовок. Но для этого конкретного примера обратных вызовов, это звездный стиль, и хорошо, что вы знаете, как их использовать. Я подозреваю, что многие новички в Ruby никогда не поймут, как это сделать хорошо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...