7

システムを値オブジェクトとサービス オブジェクトに分割すると仮定します (「テストによって導かれるオブジェクト指向ソフトウェアの成長」で提案されているように)。

値オブジェクトの 1 つが突然サービスにアクセスしてそのメソッドを実装する必要がある場合はどうなりますか?

素敵でシンプルな Value オブジェクトがあるとしましょう。それは不変で、いくつかの情報を保持しています。それだけです。次のように使用するとしましょう。

CreditCard card = new CreditCard("4111-1111-1111-1111", "07/10");
if (card.isValid())
{
  // do stuff
} 
else
{
  // don't do stuff
}

ここまでは順調ですね。 isValid()カード番号にチェック ディジット アルゴリズムを実装し、true/false を返します。

ここで、現在の時刻に対して有効期限を検証することでシステムを強化したいとしましょう。値オブジェクト/サービス オブジェクトのパラダイムを壊さずにこれを行うにはどうすればよいでしょうか? このクラスが引き続き単体テスト可能であってほしいと思います。

  • CreditCard現在は依存関係がありますが、作成方法が原因で注入できないため、依存性注入はアウトです。
  • クラスはシングルトンを呼び出すべきではありません(CreditCardシングルトンへのグローバルアクセスは悪い習慣であるという立場です)
  • 動作をオンにCreditCardVerificationService.validateCard()するということは、既存のすべてのコードを再検討する必要があることを意味します。isValid() の実装がリークしています。

これを回避するためにできることがあることは知っていますが、最もクリーンな方法は何ですか?

4

3 に答える 3

4

何かを検証するのは CreditCard オブジェクトの仕事ではないと私は主張します。工場はチェック ディジットを検証して、適合するカードをインスタンス化していることを確認し、検証サービスはカードの有効期限/$ 制限を検証します。

于 2010-06-25T12:24:54.223 に答える
1

CreditCardそれは値オブジェクトではないと言いたくなるでしょう。

C2ウィキから:

値オブジェクトの例としては、数値、日付、金額、文字列などがあります。通常、それらは非常に広く使用されている小さなオブジェクトです。それらの ID は、オブジェクトの ID ではなく状態に基づいています。このようにして、同じ概念的な値オブジェクトの複数のコピーを持つことができます。

値オブジェクトは BusinessObject/ReferenceObject ではありません。BusinessObject/ReferenceObject は世界で見つけたものであり、ValueObject は何かの尺度または説明です。

CreditCardNumber値オブジェクトである可能性がある場合はCreditCard、検証などのビジネス ロジックを含むビジネス オブジェクトのように見えます。

私は通常、値オブジェクト、サービス、およびビジネス オブジェクトを持っています。「Growing Object-Oriented Software」については知りませんが、Value Object と Service だけに限定するのは奇妙に思えます。

于 2010-06-25T12:52:38.613 に答える
0

エンティティは永続的で一意の ID を持つ可能性が高いため、値オブジェクトCreditCardではなくエンティティと呼びます。

いずれにせよ、エンティティ クラスがサービス クラスを使用することはまったく問題ありません。上記のサービスの実装を外部構成に基づいて実行時に選択する必要がない場合は、クライアント メソッド内で目的のサービス クラスをインスタンス化して使用するだけです。一部の人が考えるかもしれないことに反して、これは単体テストを妨げるものではありません。モッキング ツールを分離に使用できるからです。

実行時にサービス実装を選択する必要がある場合は、Service Locatorを使用できます。このパターンは、専用のモック ツールを必要とせずに、モック/偽造を直接サポートできます。「新しい」オブジェクトへの注入をサポートする DI フレームワークを使用することも、別の方法です。

于 2011-03-28T20:16:57.920 に答える