インスタンス変数が多すぎるとコードが重複しますか?


19

パターンのリファクタリングによると:

クラスが多くのことをしようとすると、多くの場合、インスタンス変数が多すぎます。クラスのインスタンス変数が多すぎる場合、複製されたコードはそれほど遅れることはありません。

インスタンス変数が多すぎるとコードが重複しますか?


2
簡単に言えば、nブール変数は、例えばの内部状態空間を作成します2^n。多くの場合、オブジェクトにはそれほど多くの観測可能な状態はありませんが、すべての状態を1つのオブジェクトに詰め込んだため、内部的にはそれらすべてを処理する必要があります。
biziclop

回答:


23

インスタンス変数が多すぎることは、コードの複製とは直接関係がありません。この一般性において、この声明は偽です。重複コードのない2つの別個のクラスを1つのクラスにスローできます。これにより、責任が分離されず、インスタンス変数が多すぎる新しいクラスが生成されますが、コードは重複しません。

しかし、実世界のレガシーコードであまりにも多くの責任を持つクラスを見つけた場合、それを書いたプログラマーはきれいなコードやSOLIDの原則を気にかけなかった可能性が高いです(少なくとも、そのコードを書いたときはそうではありません)おそらく、そこに重複コードのような他のコードの匂いがするでしょう。

たとえば、「コピーと貼り付けの再利用」アンチパターンは、適切なリファクタリングを行わずに、古いメソッドをコピーし、それに若干の変更を加えることで適用されることがよくあります。時には、これを機能させるために、メンバー変数を複製し、その変数も少し変更する必要があります。これにより、クラスのインスタンス変数が多すぎる可能性があります(より正確には、非常に類似したインスタンス変数が多すぎます)。このような状況では、同様のインスタンス変数は、クラス内の他の場所で繰り返されるコードのインジケーターである可能性があります。ただし、ご指摘のとおり、これは人為的な例であり、一般的なルールを結論付けるものではありません。


11

インスタンス変数が多すぎると、状態が多すぎます。状態が多すぎると、各状態でわずかに異なるだけのコードが重複します。

これは、サブクラスまたはコンポジションである必要があることが多すぎる古典的な単一のコンクリートクラスです。

インスタンス変数が多すぎるいくつかのクラスを見つけてください。それらはあまりにも多くの状態を維持し、それぞれの場合にわずかに特化されているだけで、再利用可能なメソッドに分解できないほど複雑なコードパスが多数あることがわかります。これも最大のソースの1つですside effects

これには少なくとも1つの例外がありますが、これはこのカテゴリに該当せず、これを修正する簡単な方法です。Immutableオブジェクトは固定状態であるため、この問題は発生しません。複雑な状態管理や副作用が発生する可能性はありません。


7

あなたが引用する文は、特定の文脈で見られることを意図しています。

私の経験によると、「多くのインスタンス変数は一般に重複したコードを示している」ことを確認できません。また、これは「コードの匂い」に属し、矛盾すると思われる匂いがあることに注意してください。こちらをご覧ください:

http://c2.com/cgi/wiki?CodeSmell

おもしろいことに、「インスタンス変数が多すぎる」と「インスタンス変数が少なすぎる」というコードの匂いがします。

しかし、インスタンス変数には、少なすぎても多すぎても問題があります。

  1. すべてのインスタンス変数は、オブジェクトの何らかのステータスを意味する場合があります。Statiは常に慎重な治療が必要です。予期しない動作を回避するために、可能なすべてのstatiの組み合わせをカバーしていることを確認する必要があります。あなたは今すぐに明確にならなければなりません:私のオブジェクトは今どのステータスを持っていますか?この角度から、多くのインスタンス変数は、クラスが維持不能になったことを示している可能性があります。また、クラスは非常に多くの統計を必要とするため、クラスが非常に多くのジョブを実行することを示している場合があります。

  2. すべてのインスタンス変数は、どのメソッドがどのように変数を変更するかを監視する必要があります。だから、突然、あなたは料理をしているすべての料理人をもう知りません。深夜に疲れてプログラムされたそれらの1つは、スープを台無しにします。繰り返しますが、このような変数が多すぎると、コードが侵入しにくくなります。

  3. 反対側:インスタンス変数が少なすぎると、多くのメソッドが多くの作業とパラメーターを使用して情報を処理しなければならない可能性があります。多くのメソッドに特定の等しいパラメーターを与え、すべてのメソッドがこのパラメーターで何らかの形で非常によく似ている場合、これを感じます。そのような状況では、コードが膨張し始めます。いくつかの簡単なものをまとめるために、多くの画面を上下にスクロールすることになります。ここでは、リファクタリングが役立つ場合があります。1つのインスタンス変数と1つの明確な入り口を導入します。次に、すべてのメソッドを解放します。

  4. 最後になりますが、クラスの多くのインスタンス変数にそれぞれセッターとゲッターがある場合、他のクラスがこの最初のクラスを正しい方法で使用していないことを示している可能性があります。「ゲッターとセッターが悪である理由」についての議論があります。要するに、クラスがをRectangle提供しgetX()、他の多くのクラスがを使用する場合rectangle.getX()、「リップル効果」(他のコードに影響を与えるコードの変更がどのくらい続くか)に対してロバストでないコードを書いているということです。タイプをからintに変更するとどうなりますdoubleか?この議論によるとrectangle.getX()、実際には多くの呼び出しが次のような呼び出しである必要があります。rectanlge.calculateThisThingForMe()。したがって、非常に間接的に、多くのインスタンス変数から重複したコードが出現する可能性があります。多くのクラスが、クラス内で移動する必要のある非常によく似た、つまりコピーされたゲッターとセッターを使用するためです。

多くのまたは少数のインスタンス変数は永続的なトレードオフのままであり、ソフトウェアの成長中に両方の方法を変更します。


R-to-Pの引用は一般的すぎるため、この回答が気に入っています。私が持ち帰るのは、十分なプロパティをクライアントが公開できる場合、クライアントがそれを取得し、それらを取得して、特定の機能の独自のバージョンを記述することです-上記の#4。問題はオブジェクトの構成と同じくらい深くまで及ぶ可能性があります-#2を参照してください:コードでこれをよく見ます。(a)「<whatever>クラスを使用しなかったのはなぜですか(この組織化されていない状態の一部を整理するために)?」または(b)「なぜ彼らは新しいクラスを作らなかったのですか?すべてを追跡することはできません。」また、一貫性のあるクラスがないために、内部的に機能を複製するいくつかのクラスがあります。
レーダーボブ

6

簡単に言えば、コード内の懸念事項の分離が不十分であると、モジュール化されていないコードになり、再利用が不十分になり、コードが重複します。

機能を繰り返そうとしない場合、コードが重複することはなく、多くのインスタンス変数は問題になりません。

機能を繰り返し実行しようとすると、モジュール化されていないモノリシックコードを再利用できなくなります。やりすぎで、できることしかできません。似ているが同じではない何かを行うには、モノリシックコードを分割するよりも、カットアンドペーストする方が「簡単」です。プログラマーは、重複したコードが地獄への道であることを知っています。

したがって、多くのインスタンス変数自体は問題の根本原因ではありませんが、問題が発生しているのは強い「におい」です。

「ずっと遅れることはない」という言葉は「必ず従う」と言うよりも弱いので、著者はそれが起こらなければならないと主張するのではなく、最終的に起こると主張している。機能を再利用する必要があるが、コードがモジュール化されていないため使用できない場合。

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