0

I have a Entity class

Public class Company
{
   public int Id {get;set;}
   public string Name {get;set;}
   .
   .
   .
   public List<Address> Addresses{get;set;}
   public List<Domain> Domains{get;set;}       
}

And The manager is supposed to use this entity class

public class CompanyManager
{
   ctor
   {}
   public Company Get(int id)
   {
   }
   public List<Company> GetList()
   {
   }
   public int Add(Company company)
   {
   }
   public bool Delete(int id)
   {
   }
}

I am confused, whether should I populate the Address list and Domainlist in Company manager or should I use a facade layer to fill these properties. My Confusion is because, Address and Domains can have Manager classes. Also, I'm not sure, whether it is good practice or not.

Charles
  • 50,943
  • 13
  • 104
  • 142
Johney
  • 87
  • 6
  • I think you're confused as to what an entity actually is: An entity is a class in your domain model whose identity does not change regardless of how many of its properties change (except the ID, which is immutable). For example, if I change my name, profession, address, etc I am still the same person (and in an object-oriented model would still have the same ID value). The `CompanyManager` class does not fit this definition - it's a repository. I might be able to help you better if you start over with this question: What's the business you're trying to model and what are its rules? – Josh Kodroff Apr 17 '14 at 13:03
  • Thanks Josh. I am trying to workout a product which will keep client details in above format. I am not comfortable with the existing code and suggesting a re-factoring change. The Product will have a UI which will pull data from service. Service will be responsible to provide viewModels by using data contracts. My intention is to keep business away from view model i.e. Data contract. So, I am suggesting different manager classes for each entity and Facade will create ultimate data contract object. So, I'm confused. – Johney Apr 17 '14 at 15:53

2 Answers2

0

First of all I highly doubt the Company is just some DTO with public setters and it's defined by collections of Address and Domain. Are they required by the Company concept to be properly defined? Are you certain that Company needs the whole Address or Domain definition or just an id is enough?

Your CompanyManger resembles A LOT to a Repository. I don't know if that's what you intended (a data access manager) or if it's actually a service containing use cases. If it's a repository then is its responsibility to restore (populate all the field) the object.

MikeSW
  • 16,140
  • 3
  • 39
  • 53
0

Per your comment above, I think you could use some general architectural advice. Here's the approach that I used, which worked for me. I'm gonna call it "CQRS-lite" in that it doesn't use event sourcing or strictly separate data sources, but it'll solve the SRP issue you're wrestling with.

Here's how we would do reading:

public class FooController {
    private IFooService _readService;

    public ActionResult List();
}

// runs DB queries, maps them to viewmodels
// If you're using EF, use one DB context per HTTP request
// and turn off change tracking
public interface IFooService  {
    FooList List();
}

// a viewmodel, only used by this controller 
// (and often only by one action/view)
public class FooList {
    public IEnumerable<FooListItem> Foos;
}

And here's how we would do writing (this is the same MVC controller - I just broke the code up between reading and writing to make it easier to read):

public class FooController {
    private IBus _bus;

    [HttpPost]
    public void Create(FooCreate model) { // could also return, e.g. RedirectToAction
        _bus.Send(new CreateFoo {
            Id = model.Id,
            // map the other properties
        })
    }
}

// e.g. NServiceBus in memory, or you can write your own
// it just finds the handler for the command via your 
// DI container
public interface IBus {
    void Send(params ICommand[] commands)
}

// A command tells the system to do something.
// It's basically a serializable remote procedure
// call, can be sync or async
public class CreateFoo : ICommand {
    public Guid Id;
    // etc
}

// A command handler.  DbContext should be scoped per-instance
// (not per HTTP request) or things get complicated.
// You can decorate Handle() with, e.g. _context.SaveChanges()
public class CreateFooHandler : IHandler<CreateFoo> {
    private IDbContext _context;

    public void Handle(CreateFoo message) {
        // write stuff to the DB
    }
}
Josh Kodroff
  • 27,301
  • 27
  • 95
  • 148