Как назвать переменную, являющуюся копией параметра?

У меня есть метод, который будет обрабатывать Collection<Nodes>, который передается как параметр. Этот Collection будет изменен, поэтому я подумал, что было бы хорошо сделать его копию. Как указать параметр и локальную переменную, например. nodes в приведенном ниже примере?

List<Nodes> process(Collection<Nodes> nodes) {
  List<Nodes> nodes2 = new ArrayList<>(nodes);
  ...
}

В качестве другого примера рассмотрим следующее, где переменная int анализируется по параметру String:

public void processUser(final String userId) {
  final int userId2 = Integer.parseInt(userId);
  ...

Ответ 1

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

В JDK существует много случаев, подобных вашим. Arrays#copyOf:

public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
    @SuppressWarnings("unchecked")
    T[] copy = ((Object)newType == (Object)Object[].class)
        ? (T[]) new Object[newLength]
        : (T[]) Array.newInstance(newType.getComponentType(), newLength);
    System.arraycopy(original, 0, copy, 0,
                     Math.min(original.length, newLength));
    return copy;
}

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

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

Edit:

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

Если это так (или подобное), я считаю, что подходящий подход вы может применяться, так это то, что каждый метод должен иметь одну ответственность. Согласно имени вашего метода, он должен обработать пользователя, для этого вам понадобится int userId. Ответ на разбор String userId должен быть вне сферы действия этого метода.

Использование предлагаемого подхода имеет, среди прочего, следующие преимущества:

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

  • Ваш класс не будет нести ответственность за обработку NumberFormatException, которая должна отвечать требованиям приложения.

  • Ваш метод processUser не изменится, если вам нужно обрабатывать разные типы входов (например, float userId).

Ответ 2

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

  • Что такое логическое (абстрактное, концептуальное) значение этой переменной?
  • Какие аспекты использования этой переменной могут смущать программистов?
  • Что самое важное в этой переменной?

Глядя на ваш первый пример, вам сложно понять, что ваша программа действительно выбирает хорошее имя. Метод называется process; но методы, вообще говоря, реализуют вычислительные процессы, поэтому это имя действительно ничего мне не говорит. Что вы обрабатываете? Каков процесс? Для кого вы его обрабатываете и почему? Знание того, что делает этот метод, и его класс, поможет сообщить имя переменной.

Добавьте некоторые предположения. Скажем, вы создаете приложение, которое находит точки доступа Wi-Fi в здании. Рассматриваемый Node - это беспроводной node, с подклассами Repeater, AccessPoint и Client. Позвольте также сказать, что это набор данных, обработанный онлайн, поэтому набор данных узлов может измениться в любой момент в ответ на фоновый поток, получающий обновления в том, какие узлы в настоящее время видны. Ваша причина для копирования коллекции во главе метода заключается в том, чтобы изолировать себя от этих изменений на время локальной обработки. Наконец, предположим, что ваш метод сортирует узлы по времени ping (объясняя, почему метод принимает общий Collection, но возвращает более специфичный тип List).

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

class NetworkScanner {
    List<Node> sortByPingTime(Collection<Node> networkNodes) {
        final ArrayList<Node> unsortedSnapshot;

        synchronized(networkNodes) {
            unsortedSnapshot = new ArrayList<>(networkNodes);
        }

        return Utils.sort(unsortedSnapshot, (x,y) -> x.ping < y.ping);
    }
}

Таким образом, метод sortByPingTime определяет, что он делает; аргумент networkNodes для описания того, что мы рассматриваем node. И переменная называется unsortedSnapshot, чтобы выразить две вещи об этом, которые не видны, просто прочитав код:

  • Это снимок чего-то (подразумевающий, что оригинал каким-то образом нестабилен); и
  • У нас нет порядка, который имеет для нас значение (предполагая, что он может быть к тому моменту, когда мы закончим).

Мы могли бы разместить там nodes, но это сразу видно из входного аргумента. Мы могли бы также назвать это snapshotToSort, но это видно в том, что мы передаем его в подпрограмму sort сразу же.

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

Другие связанные примечания:

  • Именование по своей сути немного субъективно. Мое имя никогда не будет работать для всех, особенно когда учитываются несколько человеческих языков.
  • Я нахожу, что лучшее имя часто не является именем. Если мне удастся сделать что-то анонимное, я это сделаю - это минимизирует риск повторного использования переменной и уменьшает символы в ячейках IDE "найти". Как правило, это также подталкивает меня писать более строгий, более функциональный код, который я считаю хорошим.
  • Некоторым людям нравится включать тип переменной в свое имя; Я всегда считал, что это немного странно, потому что тип обычно очевиден, и компилятор обычно поймает меня, если я все равно ошибаюсь.
  • "Keep it Simple" находится в полной силе здесь, как и везде. В большинстве случаев ваше имя переменной не поможет кому-то избежать будущей работы. Мое эмпирическое правило, назовите его чем-то немым, и если я когда-нибудь в конце концов почесываю голову о том, что что-то значит, выберите этот случай, чтобы назвать его чем-то хорошим.

Ответ 3

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

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

Если это не важно, какая обработка выполняется и какой тип ввода, наиболее общей является эта форма:

List<Nodes> process(Collection<Nodes> input) {
  List<Nodes> output = new ArrayList<>(input);
  ...
}

и

public void process(final String input) {
    final int output = Integer.parseInt(input);
    ...

Если важно предоставить больше информации о обработке и типе ввода, имена, такие как: processCollection, inputCollection и processUser, inputUserId более подходят, но локальная переменная по-прежнему является результатом - это ясное и самоочевидное имя

List<Nodes> processCollection(Collection<Nodes> inputCollection) {
  List<Nodes> output = new ArrayList<>(inputCollection);
  ...
}

и

public void processUser(final String inputUserId) {
    final int output = Integer.parseInt(inputUserId);
    ...

Это зависит от варианта использования, и иногда даже более целесообразно разрабатывать обработку, которая выполняется: asArray или asFilteredArray и т.д. вместо processCollection.

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

Ответ 4

Это зависит от того, что вы собираетесь делать с локальной переменной.

Например, в первом примере кажется, что, вероятно, переменная nodes2 будет фактически значением, возвращаемым в конце. Мой совет - просто называть его result или output.

Во втором примере... менее понятно, чего вы можете достичь... Я думаю, что userIdAsInt должно быть хорошо для локального. Однако, если здесь всегда ожидается int, и вы все равно хотите сохранить параметр как строку (возможно, вы хотите вывести эту проверку из метода), я думаю, что более целесообразно сделать локальную переменную userId и параметр userIdAsString или userIdString, который намекает, что String, хотя и принят здесь, не является каноническим представлением userId, которое является int.

Ответ 5

Конечно, это зависит от фактического контекста. Я бы не использовал подходы с других языков программирования, таких как _, который хорош, например, для именования скриптов bash, IMO my тоже не является хорошим выбором - это похоже на фрагмент кода, скопированный из учебника (по крайней мере в Java).

Самое простое решение - назвать параметр метода nodesParam или nodesBackup, а затем вы можете просто пойти с nodes в качестве копии или, если быть более конкретным, вы можете назвать его nodesCopy.

В любом случае, ваш метод process выполняет некоторые задачи, и, возможно, это не лучшее место для создания копий списка узлов. Вы можете сделать копию в том месте, где вы вызываете метод, тогда вы можете просто использовать nodes как имя вашего объекта:

List<Nodes> process(Collection<Nodes> nodes) {
  // do amazing things here
  // ...
}

// ...
process(new ArrayList<>(nodes))
// ...

Просто я предполагаю, что у вас есть коллекция, и вы хотите сохранить оригинальную версию и изменить копию, может быть, для вас действительно нужно использовать java.util.stream.Stream.

Ответ 6

Проще говоря, при указании переменной я считаю несколько вещей.

  • Как создается копия? (Преобразуется ли он из одного типа в другой?...)
  • Что я буду делать с переменной?
  • Является ли имя коротким, но/и значимым?

Учитывая те же примеры, которые вы указали в вопросе, я назову такие переменные:

List<Nodes> process(Collection<Nodes> nodes) {
  List<Nodes> nodesCopy = new ArrayList<>(nodes);
  ...
}

Это, вероятно, просто копия коллекции, отсюда и название nodesCopy. Значительный и короткий. Если вы используете nodesList, это может означать, что это не просто Collection; но и List (более конкретный).

public void processUser(final String userId) {
  final int userIdInt = Integer.parseInt(userId);
  ...

Анализируется String userId, а результат - целое число (int)! Это не просто копия. Чтобы подчеркнуть это, я бы назвал это как userIdInt.

Лучше не использовать символ подчеркивания _, потому что он часто указывает переменные экземпляра. И префикс my: здесь не так много смысла, и это nooby (local будет лучше).

Ответ 7

Когда речь идет о соглашениях об именах параметров метода, если вещь, представленная параметром метода, не будет представлена ​​какой-либо другой переменной, используйте имя параметра метода, которая очень четко определяет, что этот параметр метода находится в контексте тела метода, Например, primaryTelephoneNumber может быть допустимым именем параметра метода в методе setBean для JavaBean.

Если в контексте метода есть несколько представлений о вещи (включая параметры метода и локальные переменные), используйте имена, которые дают понять людям, что это за вещь и как ее использовать. Например, для имени параметра метода могут использоваться providedPrimaryTelephoneNumber, requestedPrimaryTelephoneNumber, dirtyPrimaryTelephoneNumber и parsedPrimaryTelephoneNumber, cleanPrimaryTelephoneNumber, massagedPrimaryTelephoneNumber для локального имени переменной в методе, предоставил первичный номер телефона.

Основная цель - использовать имена, которые дают понять людям, читающим исходный код сегодня и завтра, о том, что происходит. Избегайте имен типа var1, var2, a, b и т.д.; эти имена добавляют дополнительные усилия и сложность в чтении и понимании исходного кода.

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