動的に型付けされた言語のプロシージャの途中で変数の型を変更するのは悪いスタイルですか?


8

変数に固定型がないPython(および場合によってはPHP)では、コードのロジックの途中で変数に対して「型変換」を頻繁に実行します。私は(必ずしも)単純なキャストについて話しているのではなく、基本的に同じ値またはデータを表すまま、変数の型を変更する関数について話しています。

たとえば、Webリクエストを実行するときに、response変数を使用してaddurlinfoオブジェクトを格納し、次にそのオブジェクトの文字列コンテンツ、および文字列をJSONとして解析して返されるディクショナリを次のようなコードで記述します。

response = urlopen(some_url)
assert response.info().type == 'application/json'

response = response.read()
logger.debug('Received following JSON response: ' + response)

response = json.loads(response)
do_something(response)

(さて、それは少し不自然な例ですが、私はそれがアイデアをうまく​​示していると思います)。これは、3つの個別の変数名を使用するよりも良いと思います。これは、a)response変数に基本的に同じ情報が含まれていること、別の型に「変換」されていること、b)以前のオブジェクトがそうではないことを伝えるためです。これらの変数を再割り当てすることで、後のコードで使用できなくなったため、関数のさらに下で必要になります。

トレードオフは、おそらく、ある時点で変数がどのタイプであるかについて読者が混乱する可能性があるということです。

これは悪いスタイルですか?上記の例では、1つに再割り当てする代わりに3つの異なる変数を使用する必要がありますか?また、これは動的に型付けされた言語での標準的な方法ですか?他の人のコードを知るのに十分なほど見ていません。

回答:


9

私は手足を出して言います:いいえ、これはひどい考えです。

これは、変数を再利用する特殊なケースにすぎません。これは悪い考えです。主に、プログラムフローの任意の時点で変数に何が含まれているかを理解するのが難しいためです。たとえば、変数を再利用する必要がありますか?を参照してください

あなたのポイントについて:あなたが上げたポイントは有効です、それは単に変数を再利用することが良い解決策ではないということです:-)。

a)応答変数には基本的に同じ情報が含まれているが、異なる型に「変換」されていることを伝える

この情報を提供することをお勧めします。ただし、同じ変数を使用してこれを行わないでください。これにより、情報が変換されたという事実がわかりにくくなります。むしろ、共通の前置/後置修飾子を持つ名前を使用してください。あなたの例では:

rawResponse = urlopen(some_url)
[...]    
jsonResponse = response.read()
[...]    
responseData = json.loads(response)
[...]

これにより、変数が密接に関連していること、および同じデータが含まれていないことが明らかになります。

b)変数に再割り当てすることにより、後のコードでそれらを使用できなくしたため、以前のオブジェクトは関数のさらに下で必要とされないことを伝えています。

繰り返しになりますが、この「もはや必要ない」ことを伝えることは良いことですが、変数を再利用してそれを行わないでください。通常、再利用の割り当てはわかりにくいため、読者を混乱させるだけです。

むしろ、変数が最後に使用されてから長く存続する場合、それはメソッド/関数が長すぎることを示しています。寿命の短い変数を含む部分をサブ関数に分割します。これにより、コードが読みやすくなり、変数の有効期間が制限されます。

注:私は通常、変数を再利用しないよりもさらに一歩進んで、一度だけ値を割り当てようとします(つまり、値を決して変更せず、不変にします)。これは主に関数型言語からのアイデアですが、コードをより明確にすることができることがわかりました。もちろん、非関数型言語では、変数(明らかな例はループ変数)を変更する必要がある場合がありますが、調べ始めると、ほとんどの場合、「新鮮な」変数は読みやすくなり、文字数が少なくなります。バグが発生しやすいコード。


6

あなたはあなたの例でURLから読んでいることを知っていますが、ファイルで同じことを試みた場合、応答がもはやファイルを指していないので、ファイルを閉じることができません、それは今あなたが取得した文字列を保持していますファイルから。

それは大きな危険です。プログラムまたはモジュールの寿命の間に変化するため、その値が何であるかを忘れる可能性があります。保持している値の型がわからないため、コードを読んでいる人を混乱させることになります。

これらは、楽しいバグの試行錯誤です。


4

一般的には、そうだと思います。それは悪いスタイルですが、変数を再利用することが必要かつ有用な場合があります。私はそれのカジュアルで怠惰な使用を避けることをお勧めします。

この例の問題は、動的型付けによるものではなく、同じ変数を使用して3つの異なるものを参照するためです。このコードを読んだとき、何をresponse指しているのかを理解するのがはるかに難しいため、このコードはあまりわかりません。

Javaのような静的に型付けされた言語で同様に厄介なことをすることができます(型階層によってさまざまなものが関連しているという制限があります)。重要な点は、単一の変数を使用して異なるオブジェクトを指すことは、型システムに関係なく混乱する可能性があるということです。


これは理にかなった異論のようです。私は、この種のスタイルをコードから段階的に排除しようと思います。フォローアップ:同じものを概念的に参照するが、型が異なるさまざまな変数にどのように名前を付けますか?ハンガリー語の表記は一種醜いであり、そして(持つようなタイプの末尾response_addurlinforesponse_strresponse_dictまだ醜いです)。職業はなんですか?
Mark Amery 2013

@MarkAmery重要なのは、変数概念的に同じものを参照していないことです。1つ目はエラーの可能性があるサーバー応答の2つ目、2つ目は有効なjsonではない可能性のあるテキスト文字列、3つ目はデータ構造です。単なる応答と型以外のセマンティクスがあります。私の経験では、適切な変数の命名は非常に困難ですが、通常は価値があります。申し訳ありませんが、これ以上具体的にすることはできません。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.