먼저 인터페이스를 공개하여 누계 루트 (즉, 주문())에 대한 참조를 가져와야합니다. 팩토리 패턴을 사용하여 집계 루트 (즉, 주문())의 새 인스턴스를 새로 만듭니다.
그렇다면 Aggregate Root의 메소드는 자체적으로가 아니라 관련된 객체에 액세스합니다. 또한 집계 루트 (예 : 사용자가 명시한 Lines() IList 컬렉션)에서 복잡한 유형을 공용으로 공개하지 마십시오. 이것은 decremeter (sp ck)의 법칙을 위반합니다. 즉, "Dot Walk"방법으로 Order.Lines.Add()와 같은 방법을 사용할 수 없다고 말합니다.
또한 클라이언트가 집계 루트의 내부 개체에 대한 참조에 액세스 할 수있게하는 규칙을 위반합니다. 집계 루트 수 내부 개체의 참조를 반환합니다. 외부 클라이언트가 해당 객체에 대한 참조를 보유 할 수없는 한. 즉, "OrderLine"을 RemoveLine()에 전달합니다. 외부 클라이언트가 모델의 내부 상태 (예 : Order() 및 OrderLines())를 제어하도록 허용 할 수 없습니다. 따라서 OrderLine이 그에 따라 작동 할 새 인스턴스가 될 것으로 기대해야합니다.의 참조를 취득 할 수있는 인터페이스를 통해 외부 클라이언트가 직접 IOrderLinesRepository에 액세스 할 수있는 권한이 있는가
public class OrderFactory
{
public Order CreateComponent(Type type)
{
// Create your new Order.Lines() here, if need be.
// Then, create an instance of your Order() type.
}
}
:
public interface IOrderRepository
{
Order GetOrderByWhatever();
}
internal interface IOrderLineRepository
{
OrderLines GetOrderLines();
void RemoveOrderLine(OrderLine line);
}
public class Order
{
private IOrderRepository orderRepository;
private IOrderLineRepository orderLineRepository;
internal Order()
{
// constructors should be not be exposed in your model.
// Use the Factory method to construct your complex Aggregate
// Roots. And/or use a container factory, like Castle Windsor
orderRepository =
ComponentFactory.GetInstanceOf<IOrderRepository>();
orderLineRepository =
ComponentFactory.GetInstanceOf<IOrderLineRepository>();
}
// you are allowed to expose this Lines property within your domain.
internal IList<OrderLines> Lines { get; set; }
public RemoveOrderLine(OrderLine line)
{
if (this.Lines.Exists(line))
{
orderLineRepository.RemoveOrderLine(line);
}
}
}
은 주문()의 새로운 인스턴스를 생성하여 공장을 잊지 마세요 집계 루트 내의 값 개체를 그러나 나는 집계 루트의 모든 방법을 사용하여 참조를 강제로 차단하려고합니다. 따라서 IOrderLineRepository를 내부로 표시하여 노출되지 않도록 할 수 있습니다.
전 실제로 모든 집계 루트 생성을 여러 팩터 리로 그룹화합니다. 나는 "어떤 집계 된 뿌리는 복잡한 유형의 공장을 갖을 것이고 다른 것들은 그렇지 않을 것"이라는 접근 방식을 좋아하지 않았다. 도메인 모델링 전반에 걸쳐 동일한 논리를 유지하는 것이 훨씬 쉽습니다. "오, Sales()는 Order()와 같은 집계 루트이기 때문에 공장도 있어야합니다."
마지막으로 SalesOrder()와 SalesOrder()의 두 모델을 사용하는 경우 SalesOrder()의 해당 인스턴스를 만들고 작동시키는 서비스를 사용하지 않을 것입니다. Sales() 또는 Order() Aggregate Root 나 저장소 또는 공장은 SalesOrder() 엔터티를 제어합니다.
도메인 드라이브 디자인 (DDD)에 Abel Avram과 Floyd Marinescu가 this free book을 매우 강력히 추천합니다. 귀하의 질문에 바로 답을 얻을 수 있습니다. 도메인 엔티티를 모듈 등으로 더 잘 분리하는 방법과 함께
편집 : 추가 더 많은 코드로
이 설명은 도메인 엔터티에서 직접 ORM을 사용하지 않는다고 가정합니다. 내가 linq SQL에 자동으로 도메인 개체에 변경 사항을 유지하게함으로써 위에서 설명한 추가 작업을 피할 수 있기를 바랬습니다 ... –
y, 그게 진짜 문제입니다. 나는 위와 같이 해왔다. Nhibernate에서 더 많은 고급 시나리오를 지원하는 의견을 항상 볼 수 있지만이 시나리오 유형 (POCO 만 사용하는 것은 아닙니다)을 사용하는 방식을 살펴 보지 않았습니다. – eglasius
감사합니다. 비록 몹시 이상적이지는 않지만 (LTS의 잘못, 당신의 대답이 아닙니다.) 이것이 어떻게해야 할 지에 대한 내 자신의 점심을 확인하는 것 같습니다 ... – Funka