Чи є причина не змінювати значення параметрів, переданих за значенням?


9

Чи існують об'єктивні, підтримувані програмно-інженерні аргументи за або проти зміни значень параметрів побічного значення в тілі функції?

Повторний плювок (здебільшого приємно) в моїй команді полягає в тому, чи слід змінювати параметри, передані за значенням, чи ні. Кілька членів команди переконані, що параметри ніколи не повинні призначатися, так що значення, яке спочатку передалося функції, завжди можна було допитати. Я не згоден і вважаю, що параметри є не що інше, як локальні змінні, ініціалізовані синтаксисом виклику методу; якщо вихідне значення параметра значення є важливим, ніж локальна змінна може бути оголошена для явного зберігання цього значення. Я не впевнений, що будь-хто з нас має дуже гарну підтримку своєї позиції.

Це нерозв’язний релігійний конфлікт, чи є хороші об'єктивні причини інженерії програмного забезпечення в будь-якому напрямку?

Примітка: Питання про принцип залишається незалежно від деталей реалізації конкретної мови. Наприклад, у JavaScript, де список аргументів завжди динамічний, параметри можуть розглядатися як синтаксичний цукор для ініціалізації локальної змінної з argumentsоб'єкта. Незважаючи на це, можна визначити ідентифікатори параметрів як "особливі", оскільки вони все ще фіксують передачу інформації від абонента до виклику.


Він все ще є специфічним для мови; стверджуючи, що мова є агностичною, оскільки "це так, з моєї (улюбленої мови) точки зору" є формою невірного аргументу. Друга причина, чому вона є специфічною для мови, полягає в тому, що питання, яке не має універсальної відповіді для всіх мов, підпорядковане культурам і нормам кожної мови; в цьому випадку різні мовні норми призводять до різних відповідей на це питання.
rwong

Принцип, якого члени вашої команди намагаються навчити вас, - це "одна змінна, одна мета". На жаль, ви не збираєтесь знайти остаточне підтвердження в будь-якому випадку. Чому це варто, я не пам’ятаю, щоб коли-небудь кооптувати змінну параметрів для якоїсь іншої мети, а також не пам'ятаю, щоб коли-небудь розглядати її. Мені ніколи не спадало на думку, що це може бути хорошою ідеєю, і я все ще не думаю, що це так.
Роберт Харві

Я подумав, що це, мабуть, просили раніше, але єдиний дуп, який я міг знайти, це це старе питання ТА .
Док Браун

3
Вважається, що мова схильна до помилок, щоб заборонити мутацію аргументів, подібно до того, як дизайнери функціональних мов вважають, що призначення "нехай" є менш схильними до помилок. Сумніваюся, хтось довів це припущення, використовуючи дослідження.
Френк Хілеман

Відповіді:


15

Я не згоден і вважаю, що параметри є не що інше, як локальні змінні, ініціалізовані синтаксисом виклику методу

Я приймаю третю позицію: параметри так само, як локальні змінні: обидва слід розглядати як незмінні за замовчуванням. Тож змінні призначаються один раз, а потім читаються лише з них, не змінюються. У випадку циклів, for each (x in ...)змінна є незмінною в контексті кожної ітерації. Причини цього:

  1. це полегшує код "виконувати в моїй голові",
  2. це дозволяє більш описові назви змінних.

Зіткнувшись із методом із купою змінних, які призначаються та потім не змінюються, я можу зосередитись на читанні коду, а не на спробі запам'ятати поточне значення кожної з цих змінних.

Зіткнувшись із тим самим методом, на цей раз із меншими змінними, але це значення постійно змінюється, тепер я повинен пам'ятати поточний стан цих змінних, а також працювати над тим, що робить код.

На мій досвід, колишньому набагато простіше на мій бідний мозок. Інші, розумніші, народніші, ніж я, можуть не мати цієї проблеми, але мені це допомагає.

Щодо іншого моменту:

double Foo(double r)
{
    r = r * r;
    r = Math.Pi * r;
    return r;
}

проти

double Foo(int r)
{
    var rSquared = r * r;
    var area = Math.Pi * rSquared;
    return area;
} 

Наведені приклади, але, на мій погляд, набагато зрозуміліше, що відбувається у другому прикладі завдяки іменам змінних: вони передають читачеві набагато більше інформації, ніж ті маси rу першому прикладі.


"локальні змінні .... слід розглядати як незмінні за замовчуванням." - Що?
whatsisname

1
Досить важко запускати forпетлі з незмінними змінними. Інкапсуляція змінної у функції недостатня для вас? Якщо у вас виникають проблеми з дотриманням змінних в одній функції, можливо, ваші функції занадто довгі.
Роберт Харві

@RobertHarvey for (const auto thing : things)- це цикл for, а змінна, яку він вводить, (локально) незмінна. for i, thing in enumerate(things):також не мутує жодних місцевих жителів
Caleth

3
Це взагалі ІМХО дуже гарна ментальна модель. Однак я хотів би додати одне: часто прийнятно ініціалізувати змінну більш ніж за один крок і розглядати її як непорушну згодом. Це не проти загальної стратегії, представленої тут, просто проти цього завжди буквально.
Док Браун

3
Нічого собі, читаючи ці коментарі, я бачу, що багато людей тут, очевидно, ніколи не вивчали функціональну парадигму.
Джошуа Джонс

4

Це нерозв’язний релігійний конфлікт, чи є хороші об'єктивні причини інженерії програмного забезпечення в будь-якому напрямку?

Це одне, що мені дуже подобається у (добре написаному) C ++: ви можете бачити, чого чекати. const string& x1є постійною посиланням, string x2є копією і const string x3є постійною копією. Я знаю, що буде у функції. x2 буде змінено, бо якби цього не було, не було б підстав робити це неконст.

Тож якщо у вас є мова, яка це дозволяє , заявіть, що ви збираєтеся робити з параметрами. Це має бути найкращим вибором для всіх учасників.

Якщо ваша мова цього не дозволяє, я боюся, що немає рішення про срібну кулю. І те й інше можливо. Єдине керівництво - принцип найменшого сюрпризу. Візьміть один підхід і виконайте його з усієї бази коду, не змішуйте його.


Ще одна хороша річ , що int f(const T x)і int f(T x)відрізняються тільки в функції тіла.
Дедуплікатор

3
Функція C ++ з таким параметром, як const int xпросто зрозуміти x, не змінюється всередині? Схоже, дуже дивний стиль для мене.
Док Браун

@DocBrown Я не суджу ні про стиль, я просто кажу, що той, хто вважає, що параметри не слід змінювати, може змусити компілятор гарантувати це, а хтось, хто думає, що змінити їх добре, може це зробити також. Обидва наміри можна чітко повідомити через саму мову, і це є великою перевагою перед мовою, яка не може її гарантувати в будь-якому випадку, і де потрібно покладатися на довільні вказівки і сподіватися, що кожен читає їх і відповідає їм.
nvoigt

@ nvoigt: якщо хтось вважає за краще змінити параметр функції ("за значенням"), він просто позбавить constйого від списку параметрів, якщо це йому заважає. Тому я не думаю, що це відповідає на питання.
Док Браун

@DocBrown Тоді це вже не const. Не важливо, чи це const чи ні, важливо, що мова містить спосіб донести це до розробника без сумнівів. Моя відповідь - це не має значення, доки ви чітко повідомляєте це , що C ++ полегшує, іншим це не можливо, і вам потрібні умовні умови.
nvoigt

1

Так, це "релігійний конфлікт", за винятком того, що Бог не читає програм (наскільки я знаю), тому він перетворюється на конфлікт читання, який стає питанням особистого судження. І я, безумовно, це зробив, і бачив, що це робиться, обома способами. Наприклад,

анульоване розповсюдження (OBJECT * object, double t0, double dt) {
  подвійний t = t0; / * локальна копія t0, щоб уникнути зміни її значення * /
  поки (що завгодно) {
    timestep_the_object (...);
    t + = dt; }
  повернення; }

Тому тут, якраз через назву аргументу t0 , я, швидше за все, вирішуватимуть не змінювати його значення. Але припустимо, замість цього ми просто змінили цю назву аргументу на tNow , або щось подібне. Тоді я б набагато більш ніж ймовірно забув про локальну копію і просто напишу tNow + = dt; за останнє твердження.

Але навпаки, припустимо, я знав, що клієнт, для якого написана програма, збирається найняти нових програмістів з дуже невеликим досвідом, які читали б і працювали над цим кодом. Тоді я б, мабуть, хвилювався про те, щоб переплутати їх із пропускною цінністю порівняно з референцією, тоді як їх розум на 100% зайнятий спробою перетравити всю ділову логіку. Тож у такому випадку я завжди декларую локальну копію будь-якого аргументу, який буде змінено, незалежно від того, чи він мені більш-менш читабельний.

Відповіді на подібні стильові питання виникають із досвідом і рідко мають канонічну релігійну відповідь. Кожен, хто думає, що існує одна і єдина відповідь (і що він це знає :), мабуть, потребує ще досвіду.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.