値で渡されるパラメーターの値を変更しない理由はありますか?


9

関数の本体にある値渡しパラメーターの値を変更することに対する、またはそれに対する反対の客観的でサポート可能なソフトウェアエンジニアリングの引数はありますか?

私のチームで繰り返されるスパッツ(大部分はおもしろい)は、値によって渡されるパラメーターを変更する必要があるかどうかです。チームのいくつかのメンバーは、パラメーターを決して割り当ててはならないことに固執しているため、最初に関数に渡された値を常に問い合わせることができます。パラメータは、メソッドを呼び出す構文によって初期化されたローカル変数に過ぎないと私は同意しません。値渡しパラメーターの元の値が重要な場合は、ローカル変数を宣言してこの値を明示的に格納できます。私たちのどちらかが私たちの立場を非常によくサポートしているとは確信していません。

これは解決できない宗教的紛争ですか、それともどちらの方向にも客観的なソフトウェアエンジニアリング上の理由がありますか?

注:原則の問題は、特定の言語の実装の詳細に関係なく残っています。たとえば、JavaScriptの場合、引数リストは常に動的であり、パラメーターはargumentsオブジェクトからのローカル変数初期化の構文糖と見なすことができます。それでも、呼び出し元から呼び出し先への情報の受け渡しをキャプチャするため、パラメータ宣言された識別子を「特別」として扱うことができます。


それはまだ言語固有です。「それはそうです、私の(好きな言語)の観点からそうだ」というのは、言語にとらわれないことは、無効な議論の形式であると主張することです。言語固有である2つ目の理由は、すべての言語に共通の答えがない質問は、各言語の文化や規範の影響を受けるためです。この場合、言語固有の基準が異なると、この質問に対する回答も異なります。
rwong

チームメンバーがあなたに教えようとしている原則は、「1つの変数、1つの目的」です。残念ながら、どちらにしても確定的な証拠を見つけることはできません。それだけの価値があるので、他の目的でパラメーター変数を選択したことを覚えていませんし、それを検討したこともありません。それが良い考えかもしれないとは思いもしませんでしたし、今でもそうは思いません。
ロバートハーベイ

これは以前に尋ねられたはずだと思いましたが、私が見つけることができる唯一の間違いは、この古いSOの質問です。
Doc Brown、

3
関数型言語の設計者が「let」代入をエラーの発生しにくいと見なすのと同じように、言語が引数の変更を禁止することはエラーの発生しにくいと見なされます。研究を使用してこの仮定を誰もが証明したとは思えません。
Frank Hileman、

回答:


15

パラメータはメソッドを呼び出す構文によって初期化されたローカル変数に過ぎないと私は同意しません

私は3番目の位置を採用します。パラメーターはローカル変数と同じです。どちらもデフォルトでは不変として扱われるべきです。したがって、変数は一度割り当てられてから、読み取られるだけで、変更されません。ループの場合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;
} 

考案された例ですが、変数名が原因で2番目の例で何が起こっているかについては、私の頭でははるかに明確rです。


「ローカル変数...はデフォルトで不変として扱われるべきです。」- 何?
whatsisname 2018

1
for不変の変数でループを実行するのはかなり難しいです。関数に変数をカプセル化するだけでは不十分ですか?単なる関数で変数の追跡に問題がある場合は、おそらく関数が長すぎます。
ロバートハーベイ

@RobertHarvey for (const auto thing : things)はforループであり、それが導入する変数は(ローカルで)不変です。for i, thing in enumerate(things):また、地元住民の変異もありません
Caleth

3
これは一般的に私見で非常に良いメンタルモデルです。ただし、追加したいことが1つあります。多くの場合、変数を複数のステップで初期化し、後で不変として扱うことは許容されます。これは、ここで説明する一般的な戦略に反するものではなく、常に文字どおりこれに従うことには反対です。
Doc Brown、

3
うわー、これらのコメントを読んで、私はここにいる多くの人々が明らかに機能的パラダイムを研究したことがないことがわかります。
ジョシュアジョーンズ

4

これは解決できない宗教的紛争ですか、それともどちらの方向にも客観的なソフトウェアエンジニアリング上の理由がありますか?

これは、(よく書かれた)C ++について私が本当に気に入っている点の1つです。const string& x1は定数参照であり、string x2はコピーでconst string x3あり、定数コピーです。私が知っている関数の中で何が起こりますか。x2 、それがなかったら、それは非const作るする理由はありませんので、変更すること。

したがって、それを許可する言語がある場合は、パラメーターを使用して何をしようとしているのかを宣言します。それは関係者全員にとって最良の選択であるべきです。

あなたの言語がこれを許可しない場合、私は銀の弾丸の解決策がないと思います。どちらも可能です。唯一のガイドラインは、最小の驚きの原則です。1つのアプローチをとり、コードベース全体でそれを使います。混同しないでください。


もう一つの良いことは、ということですint f(const T x)し、int f(T x)機能・身体だけ異なっています。
デュプリケータ

3
const int xxを明確にするためのようなパラメータを持つC ++関数は内部で変更されませんか?私には非常に奇妙なスタイルのように見えます。
Doc Brown

@DocBrownどちらのスタイルも判断していません。パラメーターを変更してはならないと考える人は、コンパイラーにそれを保証させることができ、パラメーターを変更しても問題ないと思う人も、そうすることができます。どちらの意図も言語自体を通じて明確に伝えることができます。これは、どちらの方法でも保証できず、任意のガイドラインに依存し、すべての人がそれらを読んで準拠することを期待する必要がある言語よりも優れた利点です。
-nvoigt

@nvoigt:誰かが(「値による」)関数パラメーターを変更したいconst場合、パラメーターリストから邪魔をすれば、パラメーターリストから単純に削除されます。だから私はこれが質問に答えるとは思いません。
Doc Brown、

@DocBrownそれでは、もはやconstではありません。constであるかどうかは重要ではありません。重要なことは、言語にはそれを開発者に間違いなく伝える方法が含まれているということです。私の答えは、あなたがそれを明確伝える限り、それは重要ではないということです。C++はそれを容易にします。
nvoigt 2018

1

ええ、それは「神の葛藤」ですが、神はプログラムを読んでいない(私の知る限り)ため、読みやすさの葛藤に格下げされ、個人的な判断の問題になります。そして、私は確かにそれを実行し、それが両方の方法で実行されたことを確認しました。例えば、

voidpropagate(OBJECT * object、double t0、double dt){
  double t = t0; / *値の変更を避けるためのt0のローカルコピー* /
  ながら(何でも){
    timestep_the_object(...);
    t + = dt; }
  戻る; }

したがって、ここでは、引数名t0のために、その値を変更しないことを選択します。しかし、代わりに、その引数名をtNowなどに変更しただけだとしましょう。次に、ローカルコピーを忘れてしまい、tNow + = dtと記述します。その最後のステートメントについて。

しかし、逆に、プログラムを作成したクライアントが、そのコードを読んで作業している、経験がほとんどない新しいプログラマーを雇おうとしていることを知っていたとしましょう。その後、私はそれらを値渡しと参照と混同することを心配するでしょうが、彼らの心はすべてのビジネスロジックを消化するために100%忙しいです。したがって、この種の場合、多少読みやすいかどうかに関係なく、変更される引数のローカルコピーを常に宣言します。

これらの種類のスタイルの質問への回答は経験とともに浮かび上がり、正規の宗教的回答はほとんどありません。唯一無二の答えがあると思っている人(そして彼がそれを知っている人)は、おそらくもう少し経験が必要です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.