Как Вы присваиваете переменную с результатом если.. еще блок?

У меня был спор с коллегой о лучшем способе присвоить переменную в если.. еще блок. Его код orignal был:

@products = if params[:category]
  Category.find(params[:category]).products
else
  Product.all
end

Я переписал его этот путь:

if params[:category]
  @products = Category.find(params[:category]).products
else
  @products = Product.all
end

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

Какой из этих двух более ясен Вам? Первое решение занимает немного меньше места, но я думал, что, объявляя переменную и присваивая ей три строки после могут быть более подвержены ошибкам. Мне также нравится видеть мой if и else выровненный, помогает моему мозгу проанализировать его!

35
задан Pierre Olivier Martel 27 May 2010 в 21:20
поделиться

11 ответов

Мне кажется, что второй вариант будет более читабельным для типичного программиста . Я не рубиновый парень, поэтому я не понимал, что if / else возвращает значение .... Итак, чтобы взять меня в качестве примера (и да, это моя точка зрения: D), второй вариант выглядит как хороший выбор.

0
ответ дан 27 November 2019 в 06:29
поделиться

инкапсуляция ...

@products = get_products

def get_products
  if params[:category]
    Category.find(params[:category]).products
  else
    Product.all
  end
end
13
ответ дан 27 November 2019 в 06:29
поделиться
@products =
if params[:category]
  Category.find(params[:category]).products
else
  Product.all
end

Другой вариант, он позволяет избежать повторения @products и поддерживает выравнивание if с else .

2
ответ дан 27 November 2019 в 06:29
поделиться

Я бы сказал, что вторая версия более читабельна для людей, не знакомых с этой структурой в ruby. Так что + за это! С другой стороны, первая структура более DRY.

По мере того, как я смотрю на это немного дольше, я нахожу первое решение более привлекательным. Я программист на ruby, но не использовал его раньше. Обязательно начну!

1
ответ дан 27 November 2019 в 06:29
поделиться

Я тоже не специалист по Ruby, но тревожные звоночки сразу же раздаются по поводу области применения второй команды, будет ли эта переменная вообще доступна после завершения вашего блока if?

1
ответ дан 27 November 2019 в 06:29
поделиться

Во-первых, если используется тройной, второй - если нет.

Первую практически невозможно прочитать.

1
ответ дан 27 November 2019 в 06:29
поделиться

Еще один подход:

category = Category.find(params[:category]) if params[:category]
@products = category ? category.products : Product.all
6
ответ дан 27 November 2019 в 06:29
поделиться

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

Как насчет ...

@products = if params[:category] Category.find(params[:category]).products
            else                 Product.all
            end

@products = if params[:category]
              Category.find(params[:category]).products
            else                
              Product.all
            end

Вы также можете попробовать ...

@products = Product.all #unless a category is specified:
@products = Category.find(params[:category]).products if params[:category]

... но это плохая идея, если Product.all на самом деле похож на функцию, которая может быть ненужной оценен.

16
ответ дан 27 November 2019 в 06:29
поделиться

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

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

Просто в качестве отступления: Этот вид if вовсе не уникален для Ruby. Он существует во всех лиспах (Common Lisp, Scheme, Clojure и т.д.), Scala, всех ML (F#, OCaml, SML), Haskell, Erlang и даже в прямом предшественнике Ruby - Smalltalk. Это просто не распространено в языках, основанных на C (C++, Java, C#, Objective-C), которыми пользуется большинство людей.

21
ответ дан 27 November 2019 в 06:29
поделиться

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

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

0
ответ дан 27 November 2019 в 06:29
поделиться

Предполагая, что ваши модели выглядят так:

class Category < ActiveRecord::Base
  has_many :products
end
class Product < ActiveRecord::Base
  belongs_to :category
end

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

#assuming params[:category] is an id
@products = Product.all( params[:category] ? {:conditions => { :category_id => params[:category]}} : {})

Или вы можете использовать сексуальную, лениво загружаемую функциональность named_scope:

class Product < ActiveRecord::Base
  ...

  #again assuming category_id exists
  named_scope :all_by_category, lambda do |cat_id|
    if cat_id
      {:conditions => {:category_id => cat_id}}
    end
  end

  #if params[:category] is a name, and there is a has and belongs to many
  named_scope :all_by_category, lambda do |cat_name|
    if cat_name
      {:joins => :categories, :conditions => ["categories.name = ?",cat_name]}
    end
  end
  ...
end

используется как

@products = Product.all_by_category params[:category]
2
ответ дан 27 November 2019 в 06:29
поделиться
Другие вопросы по тегам:

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