Search code examples
listmethodsseparation-of-concerns

Preferred way to "move" an object between lists


I have two separate lists of entities:

class EntityCollection : IList<Entity>
{
    //...
}

EntityCollection Foo;
EntityCollection Bar;

I want to implement an operation to move an object Qux that is on list Foo to Bar. What's the best way to implement it?

  • As a MoveTo instance method on EntityCollection:

    public void MoveTo(EntityCollection to, Entity entity);
    
    // Client code
    Foo.MoveTo(Bar, Qux);
    
  • As a MoveFrom instance method on EntityCollection:

    public void MoveFrom(EntityCollection from, Entity entity);
    
    // Client code
    Bar.MoveFrom(Foo, Qux);
    
  • As a static Move method on EntityCollection:

    public static void Move(Entity entity, EntityCollection from, EntityCollection to);
    
    // Client code
    EntityCollection.Move(Qux, Foo, Bar);
    
  • As a Move instance method on the class that holds boths collections:

    public void Move(Entity entity, EntityCollection from, EntityCollection to);
    
    // Client code
    Holder.Move(Qux, Foo, Bar);
    

Alternatively, and since the entities can only be in one collection at a time, I could have the entities track their location themselves, and implement it on the entity itself:

    public void MoveTo(EntityCollection to)
    {
       if(Location != null)
           Location.Remove(this);
       to.Add(this);
       Location = to;
    }

    // Client code
    Entity e;
    e.MoveTo(Foo);

    // Later on...
    e.MoveTo(Bar);

When presented with so many options, I want to know: where does the move method belong? And why?


Solution

  • Ultimately, I don't think it matters too much, so my soft answer would be to not fret.

    Linguistically, MoveTo seems more natural than MoveFrom -- though I can imagine implementing both for completeness.

    Conceptually, it feels to me like neither collection instances nor the entity being moved is "responsible" for the moving, and that might incline me to put this as a static method -- otherwise you are imparting some extra importance to one of the three things in operation.

    Constructing a Holder to then accomplish the move seems pretty excessive.

    But it's up to you really, and more knowledge of how these things will be typically consumed may inform what the "right" solution is.