POCO、DTO、DLL、および弱のドメインモデル
-
23-08-2019 - |
質問
私は見る 差POCOとDTO (こPOCOのdtoの挙動(方法を教えてください。))った この記事 マーティンファウラーの弱のドメインモデルです。
通などの理解が不十分なと思い作成したこれらの弱のドメインモデルです。
一つの応用とってい事業ドメイン事業体の定義にdto'dll.る、寺子屋たすく文庫の山本ごとの特性getterおよびsetterのそれ以上ではありません。私のビジネスロジックをコードを生成の計算においては、は他'bll'dll、およびデータアクセスコードは'ダル'dll."ベストプラクティス"と考えました。
では私をdtoはこのように:
dto.BusinessObject bo = new dto.BusinessObject(...)
でのbll層はこのように:
bll.BusinessObject.Populate(bo);
ると、一部ロジックすることで、ダル層はこのように:
dal.BusinessObject.Populate(bo);
からも、私dtoの入POCOのためのビジネスロジックおよび行動(方法)の一部のオブジェクトです。その代わりに上記のコードになっちゃうんだよね:
poco.BusinessObject bo = new poco.BusinessObject(...)
bo.Populate();
ります。私のメソッドを呼び出すと、オブジェクトの継いでいるのではなく、オブジェクト研究"に関するお問合せ
私の質問です-する方法を教えてください、このまま残されて"ベストプラクティス"積層の懸念(別dllのしします。ないメソッドを呼び出すと、オブジェクトの平均の方法が定められている必要がある、オブジェクト?
以下の私の混乱した。
解決
通常、にんにしようとしている持続性へのドされていないため、そのビジネスモデル(航空機な構築し、飛翔において、旅客-貨物の場所から別の場所に).をお使いください リポジトリのパターン, では、 ORMの枠組み, 又はその他のデータにアクセスパターンを管理する永続的な保存とretreivalのオブジェクトの 状態.
の貧血のドメインモデルが遊びがやっているもののようになります:
IAirplaneService service = ...;
Airplane plane = ...;
service.FlyAirplaneToAirport(plane, "IAD");
この場合、管理の飛行機の状態から飛びながらも、その出発時間/空港の到着時間/空港の飛行計画等)に委任何外部の平面...のAirplaneServiceインスタンス.
A POCO実現にはこのデザインをインターフェースにこの方法:
Airplane plane = ...;
plane.FlyToAirport("IAD");
これにより含め開発者の知見を航空機フライでの航空います。することも可能にすることを保証するための状態 のみ 管理されます。きもののように現在の位置を読み取り専用となっていないかご確認くだけを変更します。と貧血のドメインのオブジェクト以降の状態を設定するかを発見する状態が変更になりがますます困難としての規模のドメインが増えます。
他のヒント
と思いを明らかにこの定義:
DTO:データ転送オブジェクト
いとして大きな役割を担ってデータの輸送は、通常、間発表層やサービス。います。一般的として実装されており、クラスがとする。
public class ClientDTO
{
public long Id {get;set;}
public string Name {get;set;}
}
BO:ビジネスオブジェクト:
ビジネスオブジェクトの事業要素と自然の間でベストプラクティスというものを含むビジネスロジックもございますすることとなります。マイケル-メドウズでも良い練習を分離データからのアクセスはこのオブジェクト。
public class Client
{
private long _id;
public long Id
{
get { return _id; }
protected set { _id = value; }
}
protected Client() { }
public Client(string name)
{
this.Name = name;
}
private string _name;
public string Name
{
get { return _name; }
set
{ // Notice that there is business logic inside (name existence checking)
// Persistence is isolated through the IClientDAO interface and a factory
IClientDAO clientDAO = DAOFactory.Instance.Get<IClientDAO>();
if (clientDAO.ExistsClientByName(value))
{
throw new ApplicationException("Another client with same name exists.");
}
_name = value;
}
}
public void CheckIfCanBeRemoved()
{
// Check if there are sales associated to client
if ( DAOFactory.Instance.GetDAO<ISaleDAO>().ExistsSalesFor(this) )
{
string msg = "Client can not be removed, there are sales associated to him/her.";
throw new ApplicationException(msg);
}
}
}
サービスまたはアプリケーションのクラス これらのクラスを代表する相互作用ユーザ-システムおよびその利用の両ClientDTO、クライアント
public class ClientRegistration
{
public void Insert(ClientDTO dto)
{
Client client = new Client(dto.Id,dto.Name); /// <-- Business logic inside the constructor
DAOFactory.Instance.Save(client);
}
public void Modify(ClientDTO dto)
{
Client client = DAOFactory.Instance.Get<Client>(dto.Id);
client.Name = dto.Name; // <--- Business logic inside the Name property
DAOFactory.Instance.Save(client);
}
public void Remove(ClientDTO dto)
{
Client client = DAOFactory.Instance.Get<Client>(dto.Id);
client.CheckIfCanBeRemoved() // <--- Business logic here
DAOFactory.Instance.Remove(client);
}
public ClientDTO Retrieve(string name)
{
Client client = DAOFactory.Instance.Get<IClientDAO>().FindByName(name);
if (client == null) { throw new ApplicationException("Client not found."); }
ClientDTO dto = new ClientDTO()
{
Id = client.Id,
Name = client.Name
}
}
}
個人的に私はそう悪いものを貧血ドメインモデルを見つけることができません。私は実際にデータだけではなく、行動を表すドメインオブジェクトを持つという考えのように。私は、このアプローチの主要な欠点は、コードの見つけやすさだと思います。あなたはそれらを使用する利用可能なアクションを知っておく必要があります。その周りを取得し、まだモデルから切り離さ行動コードを維持するための一つの方法は、行動のためのインターフェースを導入することである。
interface ISomeDomainObjectBehaviour
{
SomeDomainObject Get(int Id);
void Save(SomeDomainObject data);
void Delete(int Id);
}
class SomeDomainObjectSqlBehaviour : ISomeDomainObjectBehaviour
{
SomeDomainObject ISomeDomainObjectBehaviour.Get(int Id)
{
// code to get object from database
}
void ISomeDomainObjectBehaviour.Save(SomeDomainObject data)
{
// code to store object in database
}
void ISomeDomainObjectBehaviour.Delete(int Id)
{
// code to remove object from database
}
}
class SomeDomainObject
{
private ISomeDomainObjectBehaviour _behaviour = null;
public SomeDomainObject(ISomeDomainObjectBehaviour behaviour)
{
}
public int Id { get; set; }
public string Name { get; set; }
public int Size { get; set; }
public void Save()
{
if (_behaviour != null)
{
_behaviour.Save(this);
}
}
// add methods for getting, deleting, ...
}
あなたはモデルから分離振る舞いの実装を保つことができますこの方法。モデルに注入されているインターフェイス実装の使用はまた、あなたが簡単に動作を模擬することができるため、テストするコードはかなり容易になります。