Это плохой стиль переназначать длинные переменные как локальное сокращение? - PullRequest
4 голосов
/ 07 июня 2011

Я предпочитаю использовать длинные идентификаторы, чтобы сохранить мой код семантически чистым, но в случае повторных ссылок на один и тот же идентификатор я бы хотел, чтобы он "убирался с пути" в текущей области видимости.Возьмите этот пример в Python:

def define_many_mappings_1(self):
    self.define_bidirectional_parameter_mapping("status", "current_status")
    self.define_bidirectional_parameter_mapping("id", "unique_id")
    self.define_bidirectional_parameter_mapping("location", "coordinates")
    #etc...

Давайте предположим, что я действительно хочу придерживаться этого длинного имени метода, и что эти аргументы всегда будут жестко закодированы.Реализация 1 кажется неправильной, потому что большая часть каждой строки занята повторением символов.Строки в целом также довольно длинные и легко превысят 80 символов, если вложены внутрь определения класса и / или блока try / исключением, что приведет к уродливому переносу строк.Давайте попробуем использовать цикл for:

def define_many_mappings_2(self):
    mappings = [("status", "current_status"),
                ("id", "unique_id"),
                ("location", "coordinates")]
    for mapping in mappings:
        self.define_parameter_mapping(*mapping)

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

В качестве компромисса я обнаружил следующее:

def define_many_mappings_3(self):
    d = self.define_bidirectional_parameter_mapping
    d("status", "current_status")
    d("id", "unique_id")
    d("location", "coordinates")

В реализации 3 длинный методс псевдонимом чрезвычайно короткой переменной «аббревиатура».Мне нравится этот подход, потому что он сразу распознается как набор повторных вызовов методов с первого взгляда, имея менее избыточные символы и намного более короткие строки.Недостатком является использование чрезвычайно короткого и семантически нечеткого идентификатора "d".

Какое решение является наиболее читабельным?Допустимо ли использование «переменной аббревиатуры», если она явно назначена из не сокращенной версии в локальной области видимости?

Ответы [ 4 ]

1 голос
/ 07 июня 2011

itertools снова на помощь!Попробуйте использовать starmap - вот простая демонстрация:

list(itertools.starmap(min,[(1,2),(2,2),(3,2)]))

print

[1,2,2]

starmap - это генератор, поэтому для фактического вызова методов вы должны использовать генератор со списком.

import itertools

def define_many_mappings_4(self):    
    list(itertools.starmap(
        self.define_parameter_mapping,
        [
            ("status", "current_status"),
            ("id", "unique_id"),
            ("location", "coordinates"),
        ] ))

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

Если define_parameter_mappingвозвращает None, тогда вы можете заменить list на any, и тогда будут выполнены все вызовы функций, и вам не нужно будет создавать этот фиктивный список.

0 голосов
/ 07 июня 2011

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

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

# 3 страдает той же проблемой, что и # 1, но немного более кратким за счет того, что требует в основном макрос итаким образом, новые и немного незнакомые термины.

# 2 просты и понятны.Он раскладывает ваши отображения в форме данных, а затем повторяет их, используя базовые языковые конструкции.Чтобы добавить новые сопоставления, вам нужно всего лишь добавить строку в массив.Вы можете в конечном итоге загрузить свои сопоставления из внешнего файла или URL-адреса вниз, и это будет легко изменить.Чтобы изменить то, что с ними делается, вам нужно всего лишь изменить тело вашего цикла for (который сам можно превратить в отдельную функцию, если возникнет такая необходимость).

Ваша жалоба на объект №2 перед "глаголом""меня совсем не беспокоит.При сканировании этой функции я вначале предположил бы, что глагол делает то, что должен делать, и сфокусировался на объекте, который теперь ясен, сразу виден и поддерживается.Только если бы возникли проблемы, я бы посмотрел на глагол, и было бы сразу видно, что он делает.

0 голосов
/ 07 июня 2011

Я думаю, что # 3 неплохо, хотя я мог бы выбрать немного более длинный идентификатор, чем d, но часто этот тип вещей становится управляемым данными, так что тогда вы обнаружите, что используете вариант # 2, где вы зацикливаетесьрезультат запроса к базе данных или что-то из файла конфигурации

0 голосов
/ 07 июня 2011

Я бы пошел с реализацией 2, но это закрытый вызов.

Я думаю, что # 2 и # 3 одинаково читабельны. Представьте, если бы у вас было 100 сопоставлений ... В любом случае, я не могу сказать, что делает код внизу, не прокручивая вверх. В # 2 вы даете имя данным; в # 3 вы даете имя функции. Это в основном стирка.

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

Разница возникает, если вы хотите изменить то, что вы делаете, к данным. Например, допустим, вы решили добавить сообщение отладки для каждого определенного вами сопоставления. С # 2 вы добавляете оператор в цикл, и его все еще легко прочитать. С # 3 вы должны создать lambda или что-то еще. В лямбдах нет ничего плохого - я люблю Лисп так же сильно, как и всех остальных, но думаю, что мне все равно будет легче читать и изменять # 2.

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

...