Search code examples
c#entity-frameworkencapsulation

How to update a complex type (model) property?


I have two models, Ship and Sector, where Ship has a property named Location which is an instance of the Sector class, and Destination which is another instance of the Sector class. Considering encapsulation the ship itself should be responsible for updating these properties, so I made a Move() method that calculates how much progression the ship made and should update the Location property accordingly. If the new location is different from the destination (there are sectors in between and the ship is halfway), how do I get a reference to the instance of that Sector?

public class Ship
{
   public Sector Location { get; set; }
   public Sector Destination { get; set; }

   public void Move() 
   {
   // some magic happens here. Now I would like to update the Location.
   }
}

I use Entity Framework and a repository pattern. So I have a SectorRepository and a ShipRepository that both implement the following interface.

public interface IRepository<T>
{
   T Get(int id);
   T Get(Expression<Func<T, bool>> predicate);
   void Add(T entity);
   void Remove(T entity);
   List<T> GetAll();
   List<T> Search(Expression<Func<T, bool>> predicate);      
}

I could make an instance of SectorRepository in the Ship model, but that feels like Tight Coupling, which I would like to avoid if possible.


Solution

  • If Ship.Move() needs to load sectors in order to record it's new position, then it would be perfectly fine to pass an implementation of the ISectorRepository interface (or an "ISectorFinderService") as a parameter to the Move() method. The key is to realise A) that interface is part of your domain model, so this doesn't violate any layers, and B) by your implementation, Ship is already tightly coupled to the concept of sectors, so passing an ISectorFinderService (with a suitable level of abstraction) doesn't really add any new conceptual dependencies.

    However, I have no idea what your sectors really represent, or how the move algorithm works. Perhaps you should have a method Sector.GetNextSector(direction)?