Delphi ユニットは「根本的に壊れている」わけではありません。それらが機能する方法により、コンパイラの驚異的な速度が促進され、クリーンなクラス設計が促進されます。
Prims/.NET が可能にする方法でクラスをユニットに分散できることは、開発者がフレームワークを適切に設計する必要性を無視できるようにすることでクラスの無秩序な編成を促進し、任意の強制を促進するため、間違いなく根本的に壊れているアプローチです。 「ユニットごとに1つのクラス」などのコード構造規則。これには、普遍的な格言としての技術的または組織的なメリットはありません。
このケースでは、この循環参照のジレンマから生じるクラス設計の特異性にすぐに気付きました。
つまり、なぜ作品がボードを参照する必要があるのでしょうか?
駒がボードから取られた場合、そのような参照は意味をなさないか、または削除された駒の有効な「MoveTargets」は、新しいゲームの「開始位置」としてその駒に対して有効なものだけですか? しかし、これは、GetMoveTargets が NIL ボード参照を使用した呼び出しをサポートすることを要求する場合の恣意的な正当化以外には意味がないと思います。
任意の時点での個々の駒の特定の配置は、チェスの個々のゲームの特性であり、同様に、任意の駒に対して可能な有効な動きは、ゲーム内の他の駒の配置に依存します。
TChessPiece.GetMoveTargetsは、現在のゲームの状態を知る必要はありません。これはTChessGameの責任です。また、TChessPieceは、指定された現在の位置から有効な移動ターゲットを決定するために、ゲームまたはボードへの参照を必要としません。ボードの制約 (8 つのランクとファイル) はドメイン定数であり、特定のボード インスタンスのプロパティではありません。
したがって、ボード、駒、そして重要なことにルールの認識を組み合わせた知識をカプセル化するTChessGameが必要ですが、ボードと駒は互いの知識やゲームの知識を必要としません。
ピース タイプ自体のクラスに別のピースに関連するルールを配置するのは魅力的に思えるかもしれませんが、ルールの多くは他のピースとの相互作用に基づいており、場合によっては特定のピース タイプとの相互作用に基づいているため、これは間違いです。このような「全体像」の動作には、特定のピース クラスでは適切ではない、ゲーム全体の状態のある程度の監視 (概要を読む) が必要です。
たとえば、TChessPawn は、有効な移動ターゲットが前方の 1 つか 2 つの正方形、または斜め前方の 1 つの正方形であると、これらの斜めの正方形のいずれかが占有されている場合に決定する場合があります。ただし、ポーンの動きによってキングが CHECK 状況にさらされる場合、ポーンはまったく移動できません。
私は単純に、ポーン クラスがすべての可能な移動ターゲットを示すようにすることでこれに取り組みます。次に、TChessGameは、これらの移動ターゲットの占有率とゲームの状態を参照して、これらのどれが有効かを判断します。2 マス前方に移動できるのは、ポーンがホーム ランクにあり、前方のマスが占有されている場合にのみ可能です。移動をブロックする = 無効なターゲット、占有されていない対角線のマスが移動を促進し、それ以外の有効な移動がキングを露出する場合、その移動も無効です。
繰り返しになりますが、一般的に適用されるルールをベースのTChessPieceクラスに配置したくなるかもしれません (たとえば、特定の動きはキングを公開しますか?)。TChessGameクラスの一般化された動作として適切に属します。
移動ターゲットに加えて、ピースは CaptureTargets も示す必要があります。これは、ほとんどのピースの場合は同じですが、場合によってはまったく異なります - ポーンが良い例です。しかし、繰り返しになりますが、すべての潜在的なキャプチャのうち、特定の動きに対して効果的なのは - 私見 - ゲームルールの評価であり、ピースまたはピースのクラスの動作ではありません.
そのような状況 (ime - ymmv) の 99% の場合と同様に、ジレンマは、クラス設計を任意のファイル編成に押し込む方法を見つけるのではなく、モデル化されている問題をより適切に表現するようにクラス設計を変更することによって、おそらくより適切に解決されます。