Что не так с выходными параметрами? - PullRequest
9 голосов
/ 16 сентября 2009

Как в SQL, так и в C #, мне никогда не нравились выходные параметры. Я никогда не передавал параметры ByRef в VB6. Что-то о том, чтобы рассчитывать на побочные эффекты, чтобы что-то сделать, просто беспокоит меня.

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

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

РЕДАКТИРОВАТЬ: интересный поворот - выходной параметр, о котором я задавал этот вопрос, использовался вместо возвращаемого значения. Когда возвращаемое значение равно «ERROR», вызывающая сторона должна обрабатывать его как исключение. Я делал это, но не доволен идеей. Коллега не был проинформирован о необходимости справиться с этим условием, и в результате было потеряно много денег, поскольку процедура молча провалилась!

Ответы [ 11 ]

28 голосов
/ 16 сентября 2009

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

Конечно, это не всегда так, но я обнаружил, что это обычно так.

Другими словами, я думаю, что вы правы, избегая их.

20 голосов
/ 16 сентября 2009

У них есть свое место. Метод Int32.TryParse является хорошим примером эффективного использования параметра out.

bool result = Int32.TryParse(value, out number);
if (result)
{
    Console.WriteLine("Converted '{0}' to {1}.", value, number);         
}
11 голосов
/ 16 сентября 2009

Боб Мартин написал об этом чистом коде. Выходные параметры нарушают основную идею функции.

output = someMethod(input)

1 голос
/ 17 сентября 2009

Мои два цента:
Я согласен, что выходные параметры относятся к практике. VBA часто поддерживают люди, плохо знакомые с программированием, и если кто-то, обслуживающий ваш код, не заметит, что параметром является ByRef, он может привести к серьезным логическим ошибкам. Также он имеет тенденцию нарушать парадигму Свойство / Функция / Суб.
Другая причина, по которой использование параметров является плохой практикой, заключается в том, что если вам действительно do необходимо возвращать более одного значения, есть вероятность, что эти значения должны быть в структуре данных, такой как класс или определенный пользователем. Тип.
Однако они могут решить некоторые проблемы. VB5 (и, следовательно, VBA для Office 97) не позволяли функции возвращать массив. Это означало, что все, что возвращало или изменяло массив, должно было бы делать это через параметр «out». В VB6 эта возможность была добавлена, но VB6 по-прежнему заставляет параметры массива ссылаться (для предотвращения чрезмерного копирования в памяти). Теперь вы можете вернуть значение из функции, которая изменяет массив. Но это будет просто медленная стрижка (из-за акробатики, которая происходит за кулисами); это также может сбить новичков с мысли, что входные данные массива не будут изменены (что будет верно только в том случае, если кто-то специально структурирует его таким образом). Поэтому я обнаружил, что если у меня есть функция, которая изменяет массив, это уменьшает путаницу, если просто использовать подпрограмму вместо функции (и это тоже будет немного быстрее).
Другой возможный сценарий: если вы поддерживаете код и хотите добавить значение out, не нарушая интерфейс, вы можете добавить необязательный параметр out и быть уверенным, что старый код не будет нарушен. Это не очень хорошая практика, но если кто-то хочет что-то исправить прямо сейчас и у вас нет времени, чтобы сделать это «правильным образом» и реструктурировать все, это может быть удобным дополнением к вашему ящику для инструментов. < br /> Однако, если вы разрабатываете вещи с нуля и вам нужно возвращать несколько значений, вам следует учесть следующее:
1. Разбить функцию.
2. Возвращение UDT.
3. Возвращение класса.

1 голос
/ 16 сентября 2009

Только в SQL ...

Полезны выходные параметры хранимой процедуры.

  1. Скажем, вам нужно вернуть одно значение. Вы "создаете #table, вставляете ... exec, выбираете @var =". Или использовать выходной параметр?

  2. Для клиентских вызовов выходной параметр намного быстрее, чем обработка набора записей.

  3. Использование значений RETURN ограничено целым числом со знаком.

  4. Проще использовать повторно (например, вспомогательная процедура проверки безопасности)

  5. При использовании обоих: наборы записей = данные, выходные параметры = состояние / сообщения / количество строк и т. Д.

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

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

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

1 голос
/ 16 сентября 2009

Предложение OUTPUT в SQL Server 2005 и далее является отличным шагом вперед для получения любых значений полей для строк, на которые влияют ваши операторы DML. Считаю, что во многих ситуациях это устраняет выходные параметры.

В VB6 параметры ByRef хороши для передачи объектов ADO.

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

1 голос
/ 16 сентября 2009

Я тоже вижу очень мало использования параметров out / ref, хотя в SQL иногда проще передать значение обратно параметром, чем набором результатов (что затем потребовало бы использования DataReader и т. Д.)

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

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

1 голос
/ 16 сентября 2009

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

0 голосов
/ 16 сентября 2009

C ++ 0x получает кортежи, анонимные структурные объекты, к которым вы обращаетесь по индексу. Программисты C ++ смогут упаковать несколько значений в одно из них и вернуть его. Есть ли в C # что-то подобное? Может ли он вернуть массив, возможно, вместо этого? Но да, выходные параметры немного неудобны и неясны.

0 голосов
/ 16 сентября 2009

Ваше мнение звучит разумно для меня.

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

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