2017-10-18 1 views
3

私はクラスOrderを持っているとしましょう。 OrderOrder.finish()メソッドを呼び出して終了することができます。 Orderが終了すると、内部的に、仕上げの日付が設定されている:ドメイン中心のアプリケーションにデータを格納する際のカプセル化をどのように尊重するのですか?

Order.java

public void finish() { 
    finishingDate = new Date(); 
} 

をアプリケーションのビジネスロジックでは、OrderfinishingDateを公開する必要はありません、それはそうゲッターのないプライベートフィールドです。

Orderを終了した後、データベースで更新したいとします。例えば、私はupdate方法とDAO有することができる:この方法では

OrderDao.java

public void update(Order order) { 
    //UPDATE FROM ORDERS SET ... 
} 

を、Iは、テーブルを更新するために、Order内部状態が必要フィールド。しかし、私はその前に、OrderfinishingDateフィールドを公開する必要はないと言っていました。

私はOrder.getFinishingDate()メソッドを追加した場合:

  1. を私がビジネス価値を追加することなく、Orderクラスの契約を変更しています、「技術的」な理由(データベース内UPDATE
  2. ためUBT私は私は内部状態を公開しているので、オブジェクト指向プログラミングのカプセル化の原則に違反しています。

これをどのように解決しますか? ORMの「エンティティ」クラスのようなゲッターを追加することは受け入れられますか?

私は、クラス自体(実装)がそれ自身をいかにして持続するかを知っている別のアプローチを見てきました。このような何か(非常に単純な例で、それだけで問題のためです):

public interface Order { 
    void finish(); 
    boolean isFinished(); 
} 

public class DbOrder implements Order { 

    private final int id; 
    private final Database db; 

    //ctor. An implementation of Database is injected 

    @Override 
    public void finish() { 
     db.update("ORDERS", "FINISHING_DATE", new Date(), "ID=" + id); 
    } 

    @Override 
    public boolean isFinished() { 
     Date finishingDate = db.select("ORDERS", "FINISHING_DATE", "ID=" + id); 
     return finishingDate != null; 
    } 

} 

public interface Database { 
    void update(String table, String columnName, Object newValue, String whereClause); 
    void select(String table, String columnName, String whereClause); 
} 

別にパフォーマンスの問題(実際には、それがキャッシュされたか何かすることができます)から、私はこのアプローチを好むが、それは多くのことを模擬するために私たちを強制的にテスト時には、すべてのロジックが「メモリ内」ではないためです。つまり、テスト中のロジックを「実行」するために必要なデータはメモリ内のフィールドだけではなく、外部コンポーネント(この場合はDatabase)によって提供されます。

答えて

2

これは私の意見では優れた所見です。いいえ、私は技術的な理由だけで受け入れ可能なメソッド、特にゲッターを追加することは考えていません。しかし、私が働いた人の大部分は、ゲッターを追加するだけで、あなたがしているように細かく考えないことを認めなければなりません。

私たちはアクセスできない何かを持続させるという問題をどうやって解決しますか?さて、ちょうどはオブジェクトにそれ自身を持続させるように依頼します。

オブジェクト自体に(または何でも)の方法を使用できます。これはビジネスの一部であるため、これは問題ありません。そうでない場合は、と考えてください。それはおそらくsendToBackend()ですか?これは、永続性の詳細をオブジェクトに入れなければならないという意味ではありません!

メソッド自体は、実際の永続性から削除できます。パラメータとしてインターフェイスを与えることができます。または、さらに下に使用できる他のオブジェクトを返すことができます。

は、プレゼンテーションのために同じ問題についてのこれらの他の回答を参照してください:

Returning a Data Structure to Display information

Encapsulation and Getters

+0

をロバートに答えてくれてありがとう。 'persist()'メソッドが実際にビジネスの一部であることは私にとっては難しいことです。私が今投稿したアプローチについてどう思いますか?編集した質問を確認してください。もう一度ありがとうございます –

+1

私はその考え方も好きですが、すべてのロジックがDBに委任されている場合にしか使用できませんが、常にそうであるとは限りません。しかし、オブジェクトがとにかくそれをいつ行うべきかを知っているならば、あなたは 'persist()'メソッドを持つ必要はありません。例えば、 'finish()'ロジックには現在の状態を自動的にデータベースに永続化することが含まれます。それはすべて正確な要件とセマンティクスに依存します。 –

関連する問題