Это хорошая практика для создания когда-то использованных переменных? - PullRequest
20 голосов
/ 20 февраля 2009

Мой коллега изменил этот код:

private void btnGeneral_Click(object sender, RoutedEventArgs e)
{
    Button button = (Button)e.OriginalSource;
    Type type = this.GetType();
    Assembly assembly = type.Assembly;
    string userControlFullName = String.Format("{0}.{1}", type.Namespace, button.Name);
    UserControl userControl = (UserControl)assembly.CreateInstance(userControlFullName);
}

к этому коду:

private void btnGeneral_Click(object sender, RoutedEventArgs e)
{
    Button button = (Button)e.OriginalSource;
    Type type = this.GetType();
    Assembly assembly = type.Assembly;
    UserControl userControl = (UserControl)assembly.CreateInstance(String.Format("{0}.{1}", type.Namespace, button.Name));
}

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

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

  • функционирует как и уменьшает комментарии (ясно, что такое "userControlFullName")
  • облегчает чтение кода, т. Е. Большая часть вашего кода "читается как английский"
  • избегает сверхдлинных операторов, заменяя их части понятными именами переменных
  • легче отлаживать, так как вы можете навести курсор мыши на имя переменной, и в случаях, например, PHP-программирование без отладчиков, проще выводить эти имена переменных, чтобы получить их значения

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

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

Ответы [ 14 ]

26 голосов
/ 20 февраля 2009

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

Но я бы тоже не утверждал, что "всегда использую когда-то использованные переменные". Пример:

String name = "John";
person.setName(name);

не нужно, потому что

person.setName("John");

читает одинаково хорошо - если не лучше. Но, конечно, не все случаи так очевидны. В конце концов, «читабельность» - это субъективный термин.

19 голосов
/ 20 февраля 2009

Все ваши доводы мне кажутся действительными.

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

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

16 голосов
/ 20 февраля 2009

Ваш коллега не выглядит последовательным.

Согласованное решение выглядит так:

private void btnGeneral_Click(object sender, RoutedEventArgs e)
{
    UserControl userControl = ((UserControl)type.Assembly).CreateInstance(String.Format("{0}.{1}", this.GetType().Namespace, ((Button)e.OriginalSource).Name));
}
6 голосов
/ 20 февраля 2009

Я полностью с тобой в этом.

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

public void OpenDocument(string filename, bool asReadonly, bool copyLocal, bool somethingElse)

Для меня это намного более читабельно:

bool asReadonly = true;
bool copyLocal = false;
bool somethingElse = true;

OpenDocument("somefile.txt", asReadonly, copyLocal, somethingElse);

.. чем:

OpenDocument("somefile.txt", true, false, true);
4 голосов
/ 20 февраля 2009

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

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

GetCustomer (). GetOrders (). Итераторы (). Далее (). GetItems (). Итераторы (). Следующий (). GetProduct (). GetName ()

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

2 голосов
/ 20 февраля 2009

Я полностью с вашим коллегой в принципе, но не в этом случае.

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

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

2 голосов
/ 20 февраля 2009

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

for (int i1 = 0; i1 < BIG_NR; i1++)
{
  for (int i2 = 0; i2 < BIG_NR; i2++)
  {
    for (int i3 = 0; i3 < BIG_NR; i3++)
    {
      for (int i4 = 0; i4 < BIG_NR; i4++)
      {
        int amount = a + b;
        someVar[i1][i2][i3][i4] = amount;
      }
    }
  }
}

... дополнительное назначение может оказать слишком большое влияние на производительность. Но в целом ваши аргументы верны на 100%.

2 голосов
/ 20 февраля 2009

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

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

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

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

2 голосов
/ 20 февраля 2009

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

1 голос
/ 20 февраля 2009

Создание новой переменной означает еще одну концепцию, которую читатель должен отслеживать. (Рассмотрим крайний случай: int b = a; c = b;) Если метод настолько сложен - в такой необходимости разбиться - что дополнительный концепт - это цена, которую стоит заплатить, то вы должны пройти весь путь и разделить это на два метода. Таким образом, вы получите и осмысленное имя, и меньший размер. (Меньше для вашего оригинального метода: если это так, как вы говорите, то людям обычно не нужно читать вспомогательный метод.)

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

...