Передача хешей вместо [закрытых] параметров метода

78
задан Alan W. Smith 7 February 2014 в 19:31
поделиться

8 ответов

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

Мое общее правило - если у вас либо много аргументов для метода (более 3 или 4), либо множество дополнительных аргументов, используйте хеш опций, иначе используйте стандартные аргументы. Однако при использовании хэша параметров важно всегда включать комментарий к определению метода, описывающему возможные аргументы.

27
ответ дан 24 November 2019 в 10:40
поделиться

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

3
ответ дан 24 November 2019 в 10:40
поделиться

Ruby имеет неявные параметры хеширования, поэтому вы также можете написать

def my_method(options = {}) 

my_method(:width => 400, :height => 50, :show_border => false)

, а с Ruby 1.9 и новым синтаксисом хеширования это может быть

my_method( width: 400, height: 50, show_border: false )

Когда функция занимает больше чем 3-4 параметра, гораздо легче увидеть, что есть что, не считая соответствующих позиций.

40
ответ дан 24 November 2019 в 10:40
поделиться

Я бы сказал, что если вы:

  1. Имеете более 6 параметров метода
  2. Передаете параметры , которые имеют некоторые обязательные, некоторые необязательные и некоторые с значения по умолчанию

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

Для тех из вас, кто говорит, что трудно понять, какие параметры принимает метод, это просто означает, что код плохо документирован. С YARD вы можете использовать тег @option , чтобы указать параметры:

##
# Create a box.
#
# @param [Hash] options The options hash.
# @option options [Numeric] :width The width of the box.
# @option options [Numeric] :height The height of the box.
# @option options [Boolean] :show_border (false) Whether to show a
#   border or not.
def create_box(options={})
  options[:show_border] ||= false
end

Но в этом конкретном примере таких простых и мало параметров, поэтому я думаю, что я бы пошел с этим :

##
# Create a box.
#
# @param [Numeric] width The width of the box.
# @param [Numeric] height The height of the box.
# @param [Boolean] show_border Whether to show a border or not.
def create_box(width, height, show_border=false)
end
7
ответ дан 24 November 2019 в 10:40
поделиться

В Ruby не принято использовать хеш вместо формальных параметров.

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

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

Не злоупотребляйте языковыми функциями, знайте, когда их использовать, а когда нет.

3
ответ дан 24 November 2019 в 10:40
поделиться

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

2
ответ дан 24 November 2019 в 10:40
поделиться

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

Вы можете увидеть этот вопрос как часть более широкого обсуждения типов Strong / Weak. См. Блог Стива Йегге здесь. Я использовал этот стиль в C и C ++ в тех случаях, когда хотел поддерживать довольно гибкую передачу аргументов. Возможно, стандартный HTTP GET с некоторыми параметрами запроса соответствует именно этому стилю.

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

1
ответ дан 24 November 2019 в 10:40
поделиться

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

В частности, имеется не экземпляр образца публикации/подписки, а очередь сообщений. Он достаточно прост для создания собственной очереди сообщений с помощью Queue {EventHandler} , где события удаляются из очереди при их вызове.

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

-121--1149680-

Из документов API :

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

Вместо выполнения сценария в $ (документ) .ready (); используйте $ (окно) .load (); или лучше, $ (изображение) .load (); . Например:

$(document).ready(function() {
    var imageContainer = '#image-container';

    $(imageContainer).children(':first').children(':first').load(function() {
        var imageSrc = $(this).attr('src'); // control test
        var imageHeight = $(this).height(); // have also tried attr('height')

        alert(imageSrc + ' ' + imageHeight);
    });
});
-121--3643256-

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

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

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

Я сделал некоторые Perl оптимизации и такого рода вещи могут стать заметными во внутренних циклов кода.

Функциональные параметры работают намного лучше.

1
ответ дан 24 November 2019 в 10:40
поделиться
Другие вопросы по тегам:

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