Where do you put the classes?

I'm not sure if there is already a nomenclature for this, but for this question, let's define two terms: peer implementation or nested implementation to illustrate how you would implement collection classes in a data model that contains many parent / child relationships.

I use the term peer to describe a scenario in which you implement collection classes at your model level, along with entity classes that basically make them peer-to-peer in your API:

public class ParentEntity
{
  private ChildEntityCollection children;
}

public class ChildEntity
{
}

public class ChildEntityCollection : ICollection<ChildEntity>
{
}

      

The main advantage here is that you can reuse the collection class in other entity classes that store child objects of the same type.

I use the term nested to describe a scenario where you implement them as a nested class:

public class ParentEntity
{
  private ChildEntityCollection children;

  public class ChildEntityCollection : ICollection<ChildEntity>
  {
  }
}

public class ChildEntity
{
}

      

The main advantage here is that each parent can implement their own collection class to store their children in a way that is most optimized for that particular parent. For example, one parent might find that the array data structure works well, while the other might use a play tree (unknown what I know, but it illustrates my point well).

I've noticed that Microsoft uses both idioms in various .NET-based frameworks. The System.Windows.Forms namespace seems to be heavily dependent on nested implementations. I also prefer this method, even if it requires more work.

Recommendations, comments, alternative ideas?

+2


source to share


7 replies


Regardless of what Microsoft may have done in the past, current .NET API design guidelines prevent the creation of nested classes that are visible outside of their parent classes. See http://msdn.microsoft.com/en-us/library/ms229027.aspx for details .



+5


source


Another option is to inject the collection class into a child class and simply name it Collection. This way you always get Child.Collection as name.



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

public class Parent
{
  private Child.Collection children;
}

      

+2


source


Personally, I prefer peer implementation, it promotes code reuse, which I don't consider to be a nested implementation. If another class needs to implement a different way of storing a collection of the same elements, then another class can be easily implemented for this scenario without restricting code reuse.

Nested customization can also lead some developers to tightly tie their code to the parent class.

+1


source


I also prefer the peer-to-peer approach. There really is no reason to nest a collection if you never use it outside of your parent class (in which case it should be a private nested class.)

+1


source


I would only use nested layout when there is only one entity in the domain model that can logically contain child entities.

For example, if you have PieceOfMail class and MailPieces collection class

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

      

then the ShipingCompany class and MailBox class, and the PostOffice class and MailRoute class and MailManBag class could ALL have a composite property printed as MailPieces, so I would use the "peer" method.

But otoh, in the same Domain, if you have a class representing the PostageDiscount type and a collection class representing the set of discounts that will be applied to the shipment, maybe the ONLY ShipmentTransaction boolean operation class contains a collection of these discounts, then I would use a nested method...

+1


source


Do you really need a ChildEntityCollection? Why not use the collection type that is provided?

  //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
{
}

      

+1


source


I usually try to avoid generating specific collection classes. Sometimes you may need a custom class, but in many cases you can just use generic classes such as Collection<T>

and ReadOnlyCollection<T>

from namespace System.Collection.ObjectModel

. This saves a lot of typing. All your collections are sourced from IEnumerable<T>

etc. And easily integrate with LINQ. Depending on your requirements, you can also expose your collections as ICollection<T>

or a different collection interface, and then allow classes with specific requirements to use highly optimized generic collections.

public class ParentEntity {

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

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

}

      

You can also wrap IList<T>

like this:

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));
    }
  }

}

      

+1


source







All Articles