Манипулировать объектами в методах вместо возврата новых объектов? - PullRequest
1 голос
/ 21 февраля 2011

Допустим, у меня есть метод, который заполняет список какими-то объектами. Каковы преимущества и недостатки следующих методов разработки

void populate (ArrayList<String> list, other parameters ...)

ArrayList<String> populate(other parameters ...)

Какой из них я бы предпочел?

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

Ответы [ 4 ]

3 голосов
/ 21 февраля 2011

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

Владелец метода populate может вернуть неизменный List (почему ArrayList?).

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

2 голосов
/ 21 февраля 2011

Кроме того, что упомянул @duffymo, второй легче понять, поэтому используйте: очевидно, что его ввод и вывод.

1 голос
/ 21 февраля 2011

Преимущества для параметра in-out:

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

Недостатки:

  • Проблемы с читаемостью.

    • Практически во всех языках, которые поддерживают аргументы функций, первый случай подразумевает «что-то сделать с записями в этом списке». Изменение аргументов нарушает принцип наименьшего удивления. Предполагается, что второе означает «дай мне список вещей», что и нужно.
    • Каждый раз, когда вы говорите «ArrayList» или даже «List», вы отнимаете немного гибкости. Вы добавляете некоторые накладные расходы к своему API. Что если я не хочу создавать ArrayList перед вызовом вашего метода? Я не должен был этого делать, если вся цель метода в жизни - вернуть мне некоторые записи. Это работа API.
  • Проблемы с инкапсуляцией:

    • Метод, которому передается список для заполнения, не может предполагать что-либо об этом списке (даже если это вообще список; он может быть нулевым).
    • Метод Передача Список не может гарантировать, что метод делает с ним. Если он работает правильно, конечно, в документации API можно сказать, что «этот метод не уничтожит существующие записи». Но, учитывая вероятность ошибок, не стоит доверять. По крайней мере, если метод возвращает свой собственный список, вызывающей стороне не нужно беспокоиться о том, что было в нем раньше. И не нужно беспокоиться об ошибке на расстоянии тысячи миль, которая может повредить данные, на которые она никогда не должна была повлиять.
  • Проблемы безопасности потоков.

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

Побочный момент: возможность указать тип списка часто приводит к зависимостям от типа списка. Обратите внимание, как вы передаете ArrayLists повсюду. Вы рисуете себя в углах, говоря «Это ArrayList», когда вам это не нужно, но когда вы передаете его дюжине методов, это дюжина методов, которые вам придется изменить. (Не совсем связанный, но только слегка тангенциальный. Вы можете изменить типы на List, а не ArrayList и избавиться от этого. Но чем больше вы передаете этот список, тем больше мест вам нужно изменить.)

Короткая версия: Если у вас нет чертовски веских причин, используйте первый синтаксис, только если вы используете существующее содержимое списка в своем методе. IE: если вы изменяете это или делаете что-то с существующими значениями. Если вы намереваетесь вернуть список записей, то возвращает список записей .

0 голосов
/ 21 февраля 2011

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

На самом деле рекомендуется НИКОГДА не изменять значение параметра, передаваемого в функцию, если вы явно не пометите его как "out""Параметр.

также будет проще использовать в выражениях

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...