Javaの:どのようにきれいにフィールドのLOTとそのカプセル化を処理するには?

StackOverflow https://stackoverflow.com/questions/768783

  •  12-09-2019
  •  | 
  •  

質問

のは、私はRPGのいくつかの種類をコーディングを担当していましょう。これは、例えば、私は知性、ダメージボーナスやヒットポイントのように、その Character GameCharacterと統計情報を追跡したいと思う、ということを意味します。

(用とそれぞれに私は、彼らが制約や行動の非常によく似たセットに従うことを確認する必要があります -

私は、プロジェクトの最後で、私はフィールドの非常に高い数の取り扱いで終わることを積極的に怖いですたとえば、私は彼らが最小と最大の間に制限することにしたい。私は、「基本値」と「一時的なボーナス」を区別することができるようにしたい。私はセッターを経由せずに両方を増減することができるようにしたいですそしてゲッター)。突然、すべてのフィールドのために私も1(2?)ゲッターとセッター4と、おそらくカップルのresettersが必要になります!全て同様に、EEK方法の多くを意味する。

10のフィールドの 私は、このようなFieldまたはintelligence.applyBonus(10)(戻り値を気にとる範囲である)ようなコードを記述することができるように、

は、乾燥に私は、hitpoints.get()クラスのものの統計をいじりのロジックをカプセル化し始めている、など私もに行ってきましたそのような長さは、これらのフィールドをグループにクラスを作成するが、それは今の時点ではありません。

さて、FieldGameCharacterを「プラグイン」しながら、私はこの問題にヒット:ほとんどのJavaの教科書は、各クラスがパブリックゲッターとセッターとのプライベートフィールドを持つべきであると言います。それは理論的にはいいですね、と私はすでにint周りのクラス全体を構築しました。しかし、あなた自身が...ゲッターを取得するためにゲッターを呼び出して見つけたとき、アイデアが固体として鳴りません。

thisCharacter.getIntelligence().get() //eeek

私はむしろ、直接フィールドにアクセスすると思います。多分それは私のPython / VB [1]「背景」ですが、私にとっては、より明確かつ直接的なクリーナーです。

thisCharacter.intelligence.get()

公共の場での(理論上の)問題は、私はそれにすべてのコントロールを与えているということです。例えばコードベースで他のいくつかの時点で、不幸によって、次のことが起こるかもしれません。

thisCharacter.intelligence = somethingThatReallyIsNull;

は微妙なバグのように聞こえる...しかし...私は意味、私は本当に心配すべきか?いずれかの私が直接、[2]、私はこれを行うべきである何かではないことのJavadocに記載されているFieldを割り当てる予定はありませんが、私は少し破れてるので、まだ私はここに新しいです。

だから私はこのトピックに関するどのようなあなたのテイクを聞きたいです。カプセル化の利点は、私が先に行くとゲッターゲッターとセッターゲッターを持っているというように...または私は健康対策にカプセルを取るべきであるとFieldフィールドとしてpublicを残す必要があるように、大規模なていますか?

<時間>

[1]はい、私は知っています。私は忘れてしようとしてきました。しかし、我々はつい最近も、C#と男のビットを見てきた、甘いプロパティではありません。まあます。

[2]コンストラクタを除いて!そして、ゲッターが故障し、コンストラクタから私を保存しません。

役に立ちましたか?

解決

私の経験では、フィールド、数、性質上、命名の状況では、のたくさんのを必要な場所ということで、フィールドの種類はとても柔軟で、あなたのプロジェクトの生涯を通じて変更される可能性がありますおそらく代わりにフィールドのマップのいくつかの並べ替えが必要になります。

たとえば値にキーから属性マップを持っています。

の属性を取得および設定のための公共の呼び出しを提供しますが、誰もがそれらを使用させてはいけない(あるいはそうではないことを確認してください)。代わりに、それぞれが興味のある、そしてそのクラスは、その属性を操作するためのすべての機能を提供して属性表現するクラスを作成します。あなたは強さを持っている場合たとえば、あなたが特定のプレーヤーオブジェクトに初期化し、その後、ゲッター、セッター(適切な検証と例外を除いてすべて)、そしておそらくボーナスと強さを計算するようなもの、などを提供している「StrengthManipulation」クラスを持つことができますます。

このの利点の一つは、あなたがあなたのプレーヤーのクラスから自分の属性の使用を切り離すことです。あなたは今インテリジェンス属性を追加するのであれば、あなただけの強度を操作するすべてのものを扱って再コンパイルする必要はありません。

直接フィールドにアクセスするためとして、それは悪い考えです。あなたは(少なくとも古いVBSで)VBでフィールドにアクセスするときは、通常、プロパティのゲッターとセッターを呼び出し、VBは単にあなたのために()の呼び出しを非表示にします。私の見解では、あなたが使用している言語の規則に適応しなければならないということです。 C、C ++、Javaでは、あなたのようなフィールドを持っていて、メソッドを持っています。メソッドを呼び出すと、常に()それを明確にそれがコールされ、他のもの(例えば、あなたが例外を得ることができる)起こるかもしれませんことを確認する必要があります。いずれにせよ、ジャワの利点の一つは、より正確な構文とスタイルです。

JavaやC ++にVBは、学校の科学的書き込みを卒業するテキストメッセージのようなものです。

ところで:いくつかのユーザビリティの研究は、それがコンストラクタにパラメータを持っているし、むしろ構築し、あなたがそれらを必要とする場合は、すべてのセッターを呼び出さない方が良いということを示しています。

他のヒント

あなたがif(player.dexterity > monster.dexterity) attacker = playerの面で考えているように、

サウンド。あなたはより多くのif(player.quickerThan(monster)) monster.suffersAttackFrom(player.getCurrentWeapon())のように考える必要があります。彼らが行うことになっているものの周りにあなたのクラスを設計し、あなたの実際の意思を表明して、裸の統計情報と周り混乱しないでください。統計はとにかく警官アウトされています。何が本当に気にすることは、プレイヤーがまたは何らかのアクションを行うことができないことができるかどうかである、またはいくつかの参照対能力/容量。 「プレイヤキャラクタが十分に強い」の観点から考える(player.canOpen(trapDoor))の代わりに、「文字は、少なくとも50の強度を持っていない」。

スティーブ・イェジは、これらの問題をカバーした(長い場合は)非常に興味深いブログ記事を持っていた:<のhref =「http://steve-yegge.blogspot.com/2008/10/universal-design-pattern.html」のrel = "nofollowをnoreferrer">ユニバーサルデザインパターンでます。

私にはそれがthisCharacter 'のように見えるだけでなく、背後のインテリジェンスに対処するための「インテリジェンス」のオブジェクトを持っているかもしれませんが、私はそれがすべてで、公開するかどうかを疑問視。あなただけのthisCharacter.applyIntとthisCharacter.getIntの代わりに、それを扱うオブジェクトを公開する必要があります。そのようなあなたの実装を公開してはいけない。

プライベートあなたのフィールドをしてください!あなたのAPIのあまりを公開することはありません。あなたは、常に将来のリリースでは、他の方法でラウンド官民た何かを作ることはできませんが。

あなたは次のMMORPGにこれを作ってあげるかのように考えてください。あなたは、バグ、エラー、不要な悪の余地がたくさんあると思います。不変の性質は最終的なものであることを確認します。

そのminiamilisticインターフェース(再生、停止、メニュー)、および内部にはまだ、このような専門的で、DVDプレーヤーを考えます。あなたは、あなたのプログラムの中で非重要なすべてのものを非表示にするでしょう。

あなたの主な苦情は、セッター/ゲッターメソッドの抽象化とはあまりありませんが、それらを使用するための言語構文と同様に

これが鳴ります。つまり、あなたは、C#のスタイルプロパティのようなものを好むます。

このような場合は、

、その後、Java言語はあなたを提供する比較的少ないがあります。あなたはゲッターやセッターに切り替えるには、その後、あなたは(あなたが全体のコードベースをコントロールしている場合、おそらくOK)行うには、いくつかのリファクタリングを持っています必要になるまで直接フィールドアクセスは、結構です。

Javaプラットフォームが要件ですが、言語がない場合は、

もちろん、その後、他の選択肢があります。 Scalaは、このようなプロジェクトのために有用である可能性があり、他の機能の多くと一緒に、例えば、非常に素晴らしいプロパティの構文を持っています。そして、すべての最高の、それはJVM上で動作するので、あなたはまだあなたがJava言語でそれを書くことによって取得したいと同じポータビリティを取得します。 :)

あなたがここに持っているように見えることは、複合モデルの単層である。

あなただけの低レベルのモデルのセットとしてそれを持つのではなく、モデルに抽象化を追加するメソッドを追加したい場合があります。

のフィールドは最終でなければなりませんので、あなたがそれらを公開するなかった場合でも、あなたが誤ってそれらにnullを割り当てることができませんでした。

「取得」プレフィックスは、すべてのゲッターのために存在しているので、それはおそらくより多くのような新たな問題よりも初期の表情だ。

  

私が先に行くと、その上のゲッターゲッターとセッターゲッターとを持っている...または私は健康対策にカプセルを取る必要があり、公共の場としてのフィールドを離れなければならないほど巨大なカプセル化の利点はありますか?

IMO、カプセル化は、民間分野を中心にゲッター/セッターを包むとは何の関係もありません。汎用ライブラリを書き込むときに小用量で、または、トレードオフが許容可能です。しかし、あなたが記述しているようなシステムで、そのA <のhref =「http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-toolbox.html」のrelに放置する場合= "nofollowをnoreferrer">アンチパターンを。

ゲッター/セッターの問題点は、これらのメソッドを持つオブジェクトとシステムの残りの部分との間に過度に緊密な結合を作成することである。

実際のカプセル化の利点の一つは、それがプロセスでシステムの残りの部分からあなたのオブジェクトをデカップリング、ゲッターとセッターの必要性を減少させることである。

むしろsetIntelligenceでGameCharacterの実装をさらすよりも、なぜGameCharacterをより良い、それはゲームシステムの役割だ反映インタフェースを与えていない?

たとえば、代わりの

// pseudo-encapsulation anti-pattern
public class GameCharacter
{
  private Intelligence intelligence;

  public Intelligence getIntelligence()
  {
    return intelligence
  }

  public void setIntelligence(Intelligence intelligence)
  {
    this.intelligence = intelligence;
  }
}

なぜこれを試してみません:?

// better encapsulation
public class GameCharacter
{
  public void grabObject(GameObject object)
  {
    // TODO update intelligence, etc.
  }

  public int getIntelligence()
  {
    // TODO
  }
}

あるいはさらに良います:

// still better
public interface GameCharacter
{
  public void grabObject(GameObject object); // might update intelligence
  public int getIntelligence();
}

public class Ogre implements GameCharacter
{
  // TODO: never increases intelligence after grabbing objects
}

他の言葉では、GameCharacterは、ゲームオブジェクトをつかむことができます。同じゲームオブジェクトをつかん各GameCharacterの効果は(とすべきである)変えることができるが、詳細は完全に各GameCharacter実装内に封入されている。

それは例えば、ゲームオブジェクトをつかむようGameCharacterが起こることができる独自のインテリジェンス更新(範囲チェックなど)、取り扱いの担当になりましたか注目してください。セッター(そしてあなたがそれを持って注意してください合併症)が消えてしまいました。あなたは状況に応じて、完全にgetIntelligence方法を省略することができるかもしれません。アレンホルブは、その論理的な結論が、しかし、そのアプローチは非常に一般的ではないようです。

(私は完全にサポート)ウリの答えに加えて、私はあなたがデータ内の属性マップを定義することを検討をお勧めしたいと思います。これは、あなたのプログラムは非常に柔軟になりますし、あなたも、あなたがする必要はありません気付いていない多くのコードを考慮されます。

属性の変更(再計算ヒット%が強度とDEXの両方に適用される場合がありますとき、

たとえば、属性は、それがデータベース内に結合するどのような分野、それが画面上に結合するものをフィールドに実行するアクションのリストを知ることができます...)

このようにそれを行うには、DBへのクラスを記述したり、画面上に表示する属性ごとにNOのコードを持っていません。あなたは、単に属性を反復し、内部に格納されている情報を使用します。

同じことは、スキルにも適用することができます - 実際には、属性やスキルは、おそらく同じ基本クラスから派生します。

。 あなたはこの道を下るした後、

、あなたはおそらく、属性やスキルを定義するために、かなり深刻なテキストファイルを自分で見つけることができますが、新しいスキルを追加するように簡単になります:

Skill: Weaving
  DBName: BasketWeavingSkill
  DisplayLocation: 102, 20  #using coordinates probably isn't the best idea.
  Requires: Int=8
  Requires: Dex=12
  MaxLevel=50

このようなスキルを追加すると、全くコード変更を必要としないだろういくつかの点で、それはすべてかなり簡単にデータで行うことができ、すべてのデータがクラスに接続された単一のスキルオブジェクトに格納されます。あなたは、もちろん、アクションを同じように定義することができます:

Action: Weave Basket
  text: You attempt to weave a basket from straw
  materials: Straw
  case Weaving < 1
    test: You don't have the skill!
  case Weaving < 10
    text: You make a lame basket
    subtract 10 straw
    create basket value 8
    improve skill weaving 1%
  case Weaving < 40
    text: You make a decent basket
    subtract 10 straw
    create basket value 30
    improve skill weaving 0.1%
  case Weaving < 50
    text: You make an awesome basket!
    subtract 10 straw
    create basket value 100
    improve skill weaving 0.01%
  case Weaving = 50
    text: OMG, you made the basket of the gods!
    subtract 10 straw
    create basket value 1000
この例ではかなり進んでいるが、

、あなたはそれが全くコードで行われるだろうか視覚化することができるはずです。あなたの「属性/スキルは」実際にメンバ変数であれば、それはコードなしでそのような何かをするだろういかに難しいかを想像します。

などEclipseのEMFとして、「モデリング」のフレームワークを使用することを検討してください。 これは、Eclipse EMFエディタのようなものを使用してオブジェクトを定義する必要、 またはプレーンXMLで、またはRational Roseのインチそれは思ったほど難しいことではありません。 あなたは、属性、制約などを定義するとフレームワークが生成します あなたのためのコード。それはこのような追加の部品に@Generatedのタグを追加します getterメソッドとsetterメソッド。あなたはコードをカスタマイズし、後で編集することができます その手で、またはいくつかのGUI経由のいずれか、およびJavaファイルを再生成します。

scroll top