2009-10-15 4 views
2

이미이 이름이 있는지 확실하지 않지만이 질문을 위해 피어 구현 또는 중첩 된 구현을 구현하여 많은 데이터를 포함하는 데이터 모델에서 컬렉션 클래스를 구현하는 방법을 보여줍니다. 상위/하위 엔티티 관계. 여기컬렉션 클래스는 어디에 두시겠습니까?

public class ParentEntity 
{ 
    private ChildEntityCollection children; 
} 

public class ChildEntity 
{ 
} 

public class ChildEntityCollection : ICollection<ChildEntity> 
{ 
} 

가장 큰 장점 :

나는 당신이 엔티티 클래스는 기본적으로 다음처럼 API 그들에게 동료를 만들기로 측면을 따라 모델 층의 컬렉션 클래스를 구현하는 경우 시나리오를 설명하는 용어 피어를 사용 동일한 유형의 하위를 저장하는 다른 엔티티 클래스에서 컬렉션 클래스를 재사용 할 수 있다는 것입니다. 중첩 된 클래스 너무 등을 구현하는 경우

나는 시나리오를 설명하기 위해 중첩 된 용어를 사용

public class ParentEntity 
{ 
    private ChildEntityCollection children; 

    public class ChildEntityCollection : ICollection<ChildEntity> 
    { 
    } 
} 

public class ChildEntity 
{ 
} 

주요 여기 장점 각 부모에서 아이를 저장하기 위해 자신의 컬렉션 클래스를 구현할 수 있다는 것입니다 그 특정 부모를 위해 가장 최적화 된 방법. 예를 들어, 하나의 상위 엔티티는 배열 데이터 구조가 잘 작동하는 반면 다른 하나는 스플레이 트리 (snplay tree)를 사용할 수 있습니다 (모호하다는 것을 알지만 내 요점은 잘 설명합니다).

Microsoft는 다양한 .NET 관련 프레임 워크에서 두 관용구를 모두 사용함을 확인했습니다. System.Windows.Forms 네임 스페이스는 중첩 된 구현에 크게 의존하는 것처럼 보입니다. 나는 더 많은 작업이 필요할지라도이 방법을 선호하는 경향이있다.

추천, 의견, 대안 아이디어?

+0

감사합니다. 정말 공개 API를 디자인해야하는 방식에 대한 관점을 추가합니다. –

답변

5

에 관계없이 마이크로 소프트가 과거에 수도 무엇인지, 현재의 .NET API를 설계 지침은 상위 클래스 외부에서 볼 수 있습니다 중첩 된 클래스의 생성을 억제. 자세한 내용은 http://msdn.microsoft.com/en-us/library/ms229027.aspx을 참조하십시오.

+1

두 가지 지침이 모두 나를 위해 자주 적용됩니다. –

+0

다른 부모가 자녀를 다르게 저장해야 할 때 부모님이하는 일을 실제로 다루는 사람은 아무도 없습니다.하지만 프레임 워크 디자인 가이드 북 (내가 한 명씩)을 다루는 것은 매우 어렵습니다. 그래서 지금은이 대답을 받아 들일 것입니다. –

+1

Microsoft의 사람들은이 책을 규칙보다 더 많은 제안으로 간주합니다. 그것이 잘못되었다고 말하는 것은 아니지만 레드 몬드에서의 경험이었습니다. – tster

1

필자는 개인적으로 피어 구현을 선호합니다. 이는 중첩 구현이 생각하지 않는 코드 재사용을 촉진합니다. 다른 클래스가 동일한 요소의 콜렉션을 저장하는 다른 방법을 구현해야하는 경우 코드 재사용을 제한하지 않고 해당 시나리오에 대해 다른 클래스를 쉽게 구현할 수 있습니다.

중첩 된 설정으로 인해 일부 개발자는 코드를 상위 클래스에 밀접하게 연결할 수 있습니다.

+0

공유 컬렉션에서 배킹 스토어로 배열을 사용하지만 부모가 정말로 Foo라는 속성으로 키가 지정된 빨강 - 검정 트리에 저장해야하는 경우 어떻게됩니까? 공유 컬렉션을 하위 클래스로 만들고 새 데이터 구조를 추가 할 수 있지만 개체가 두 번 메모리를 소비하고 갑자기 모두 O (n)이됩니다. –

+0

+1 아주 넓은 의미에서 중첩 된 클래스가 상위 클래스에 밀접하게 결합되어 있다는 진술을 좋아합니다. 그러나 때로는 그렇게하는 것이 장점이라고 생각합니다. 가능한 코드를 재사용 할 수 있도록 노력합니다. 그러나 때로는 여러 가지 목적으로 사용될 수는 있지만 실제로 이러한 목적 중 하나를 최적으로하지는 않습니다. –

2

또 다른 옵션은 컬렉션 클래스를 하위 클래스에 중첩시키고 Collection으로 이름을 지정하는 것입니다. 그런 식으로, 당신은 항상 Child.Collection을 얻습니다.

public class Child 
{ 
    public class Collection : ICollection<Child> 
    { 
    } 
} 

public class Parent 
{ 
    private Child.Collection children; 
} 
+0

다른 질문이지만 좋은 생각입니다 ... –

+0

흠 ... 여기서 의미는 자식 엔티티가 다른 사람들이 어떻게 그 자체의 컬렉션을 저장하는지를 지시하게된다는 것입니다. 실제로 이것은 단순한 바닐라 피어 구현보다 더 나빠 보입니다. –

+0

@ 브라이언, 어떻게 그렇게? 컬렉션 클래스를 중첩하면 형식을 고유하게 식별하는 데 필요한 네임 스페이스 접두사 만 변경됩니다. 맞습니까? –

1

나는 또한 피어 접근법을 선호합니다. 결코이 부모 클래스 외부에서 사용하는 경우에만 컬렉션을 중첩 할 필요가 없습니다. (이 경우 개인 중첩 클래스 여야합니다.)

+0

"그 경우에는 개인 중첩 클래스 여야합니다."- 중첩 된 클래스의 공용 속성에 노출 될 수 있기 때문에 사실이 아닙니다. (하지만 여전히 다른 클래스가 컬렉션의 구현이 외부 클래스와 밀접하게 결합되어 있기 때문에 동일하게 수행합니다. –

+0

"부모 클래스의 외부에서 절대 사용하지 않으면"이 내용을 다루지 만 이는 중요한 고려 사항입니다. – oltman

+0

그래서 같은 유형의 객체를 다른 방식으로 저장해야 할 때 어떻게합니까? 여러 수집 클래스를 만들고 중첩하지 않고 EntityCollectionForPurposeA 및 EntityCollectionForPurposeB를 호출합니까? –

1

중첩 된 배열은 논리적으로 자식 엔티티를 포함 할 수있는 도메인 모델의 하나의 엔티티.

예를 들어

당신이 가지고있는 경우 PieceOfMail 클래스 다음하여 우편물 컬렉션 클래스

class PieceOfMail { } 
    class MailPieces: Collection<PieceOfMail> { } 

ShipingCompany 클래스 및 사서함 클래스 및 우체국 클래스 및 MailRoute 클래스와 MailManBag 클래스, 수 모두는 MailPieces로 입력 된 구성 속성을 가지고 있으므로 "피어"기술을 사용합니다.

그러나 동일한 도메인에서 PostageDiscount 유형을 나타내는 클래스가 있고 발송물에 적용 할 할인 세트를 나타내는 컬렉션 클래스가있는 경우 ShipmentTransaction 클래스 만이 논리적으로 그 할인의 콜렉션을 포함하면 중첩 된 기술을 사용할 것입니다 ...

+0

재미있는 관점. –

1

정말 ChildEntityCollection이 필요합니까? 왜 제공되는 컬렉션 유형을 사용하지 않습니까?

//why bother? 
//public class ChildEntityCollection : ICollection<ChildEntity>{} 

public class ParentEntity 
{ 
    //choose one 
    private ChildEntity[] children; 
    private List<ChildEntity> childrenInList; 
    private HashSet<ChildEntity> childrenInHashSet; 
    private Dictionary<int, ChildEntity> childrenInDictionary; 
    // or if you want to make your own, make it generic 
    private Balloon<ChildEntity> childrenInBalloon; 
} 
public class ChildEntity 
{ 
} 
+0

그래, 대부분의 경우 충분하다고 말할 수 있습니다. –

1

일반적으로 특정 컬렉션 클래스를 생성하지 않도록하십시오. 때로는 특별한 클래스가 필요할 수도 있지만 많은 경우에 System.Collection.ObjectModel 네임 스페이스의 Collection<T>ReadOnlyCollection<T>과 같은 일반 클래스를 사용할 수 있습니다. 이렇게하면 많은 타이핑을 절약 할 수 있습니다. 모든 컬렉션은 IEnumerable<T> 등에서 파생되었으며 LINQ와 쉽게 통합됩니다. 요구 사항에 따라 컬렉션을 ICollection<T> 또는 다른 컬렉션 인터페이스로 노출 한 다음 특정 요구 사항이있는 클래스가 고도로 최적화 된 제네릭 컬렉션을 사용하게 할 수도 있습니다.

public class ParentEntity { 

    Collection<ChildEntity> children = new Collection<ChildEntity>(); 

    public Collection<ChildEntity> Children { 
    get { 
     return this.children; 
    } 
    } 

} 

당신은 또한이 같은 IList<T>을 포장 할 수 있습니다 응답하는 모든 사람에 대한

public class ParentEntity { 

    // This collection can be modified inside the class. 
    List<ChildEntity> children = new List<ChildEntity>(); 

    ReadOnlyCollection<ChildEntity> readonlyChildren; 

    public ReadOnlyCollection<ChildEntity> Children { 
    get { 
     return this.readOnlyChildren 
     ?? (this.readOnlyChildren = 
       new ReadOnlyCollection<ChildEntity>(this.children)); 
    } 
    } 

} 
관련 문제