I would like to know if you find the following pattern meaningful in domain driven design.
The domain layer consists of model and repository. The application layer consists of services that handles queries from the user interface, or from controllers in the Model-View-Controller pattern.
Details of the structure:
// Assembly Model:
public class Phrase
{
public int PhraseId { get; private set; }
public string PhraseText { get; private set; }
public Phrase(string phraseText) { this.PhraseText = phraseText; }
public void SetId(int phraseId) { this.PhraseId = phraseId; }
}
// Assembly Repository (references assembly Model):
public interface IPhraseRepository
{
Phrase SavePhrase(Phrase phrase);
Phrase GetPhrase(int phraseId);
}
// Assembly Services (references assemblies Model and Repository):
public class PhraseService
{
private IPhraseRepository _phraseRepository;
public PhraseService(IPhraseRepository phraseRepository)
{
_phraseRepository = phraseRepository;
}
public Phrase SavePhrase(string phraseText)
{
Phrase phrase = _phraseRepository.SavePhrase(new Phrase(phraseText));
// doing other things like sending mail, logging, etc.
// ...
return Phrase;
}
}
Particularly, would it make sense to move the method into the Phrase entity class? In that case, how would that be called?
EDIT:
The example above has been modified after the answer from moffdub and the comment from Adeel Ansari. The changes are highlighted.
I would like to ask about the added IPhraseRepository.GetPhrase(phraseId) and how you would include that?
The repository should take in a Phrase, not a string. I'm also not sure why the SavePhrase method returns a Phrase. I tend to make such methods void methods.
Also, be wary of making every property in your domain model have public getters and setters. That can lead you to an anemic domain model.
Just some thoughts:
SetId(int phraseId) should not be public
Phrase could implement IPhrase (or IPhraseAggregate) which would not expose SetId(..)
SavePhrase(Phrase phrase) could (should?) return void if the reference to the phrase entity stays "valid" after saving:
public void SavePhrase(string phraseText)
{
Phrase phrase = new Phrase(phraseText); // NOTE: keep a reference to phrase
this._phraseRepository.SavePhrase(phrase); // NOTE: returns void
return phrase; // NOTE: assume the repository sets the phrase.PhraseId
}
Related
I'm working with autofac. So far i resolve all my dependencies with constructor injection.
There is a case where i get stuck:
Considering the given customer class:
public class Customer : ICustomer
{
public string Name { get; set; }
private int ExternId { get; set; }
public IExternalIdProvider externalIdProvider { get; set; }
public Customer()
{
this.externalIdProvider = new ConcreteIdProvider(this);
}
public BevorSave()
{
this.ExternId = externalIdProvider.GetNextId();
}
}
In Order to create a new customer object based on a request or gui action. I use the new Operator. However - There is an IdProvider within the CustomerClass i want to inject. (as property).
If the Customer would be resolved by the ioC Container i would use a configuration like:
builder.RegisterType<ConcreteIdProvider>().As<IExternalIdProvider>();
builder.RegisterType<Customer>().As<ICustomer>()
.OnActivated(ae =>
{
IExternalIdProvider idProvider =
ae.Context.Resolve<IExternalIdProvider>(TypedParameter.From(ae.Instance));
ae.Instance.externalIdProvider = idProvider;
});
My Question is: How can I inject the behaviour of the ExternalIdProvider in the Customer? (using autofac)
This article shows a sample, how this would be done with a service locator:
http://blogs.msdn.com/b/simonince/archive/2008/06/30/dependency-injection-is-dead.aspx
Thanks for your help.
You should reconsider having behavior on your entities. Having behavior in your entities forces you to do dependency injection on them, and this leads to an awkward situation, which you already noticed. Take a look at this related SO question and Mark Seemann's great answer.
So instead of having these operations on the Customer class, move them to an repository class. Other patterns to look at are unit of work, commands and queries.
I am working with an internet application that has high demands for performance which means that a good caching functionality is crucial for our success.
The solution is built with Entity Framework Code First for the database access and Postsharp for caching. For the moment the model looks something like below.
public class Article
{
private readonly IProducerOperator _producerOperator;
public Article(IProducerOperator operator)
{ _producerOperator = operator; }
public int Id { get; set; }
...
public int ProducerId { get; set; }
public Producer Producer {
get { return _producerOperator.GetProducer(ProducerId); }
}
}
The operations classes looks like below.
public class ArticleOperations : IArticleOperations
{
private readonly IDataContext _context;
public ArticleOperations(IDataContext context)
{ _context = context; }
[Cache]
public Article GetArticle(int id)
{
var article = _context.Article.Find(id);
return article;
}
}
public class ProducerOperations : IProducerOperations
{
private readonly IDataContext _context;
public ProducerOperations(IDataContext context)
{ _context = context; }
[Cache]
public Producer GetProducer(int id)
{
var producer = _context.Producer.Find(id);
return producer;
}
}
I am NOT fond of having dependendencies in the business objects but the argument for it is to having lazy loading from the cache... for the most. This solution also means that caching is done only once for producer... at GetProducer. Normally I would not even consider having dependencies there. The objects should be POCOs, nothing more. I would really need some new inputs on this one. How can I do it instead? Is this the best way?
We also need to resolve the opposite, ie, from a producer that is cached we should be able to retrieve all its articles.
First, i wish to say, there are actually some (one?) solutions that uses entity framework code first in combination with caching using postsharp. Ideablades has released Devforce code first that actually is doing exactly this. That kind of framework actually resolves it all and we can use the entity framework as it is supposed to be used, and in combination with caching.
But that did not become the solution in this case. We went for complete separation of concern, meaning that the business objects only concern went to be only containing the data. The operations classes got the responsibility to fill the business objects.
Here's a simple example of a problem I'm running across that is not meshing with some of the ideas presented here and other places regarding DDD.
Say I have an ASP.NET MVC 3 site that creates/manipulates a person. The controllers access an application service layer (PersonService) which in turn uses the domain entities (EF 4 POCO) and the PersonRepository to make changes and persist them. I'm leaving out all interfaces here for simplicity. Person is the root in this case and for simplicity only has email addresses (also assume email is not immutable and can be updated).
Option 1:
Try to stick with [my understanding] of the basics of DDD where behavior directly related to the entity is implemented as part of the entity (Person implements AddEmail, ChangeEmail, etc). The only problem with this, with the exception of the Add* methods, is that the Person would need to know about the context or entity framework pieces (which would remove any persistence ignorance) or need to use a "service" or repository to mark the email as modified.
// Person Service
public class PersonService {
// constructor injection to get unit of work and person repository...
// ...methods to add/update a person
public EmailAddress AddEmailAddress(int personId, EmailAddress email)
{
Person p = personRepository.Find(p => p.Id == personId).First();
p.AddEmail(email);
uow.SaveChanges();
return email;
}
public EmailAddress ChangeEmailAddress(EmailAddress email)
{
Person p = personRepository.Find(p => p.Id == personId).First();
p.ChangeEmail(email);
// change state of email object here so it's updated in the next line???
// if not here, wouldn't the Person entity have to know about the context
// or use a service?
uow.SaveChanges();
return email;
}
}
// Person Repository
public class PersonRepository
{
// generic repository implementation
}
// Person Entity
public class Person
{
public string Name { get;set; }
public IEnumerable<EmailAddress> EmailAddresses { get;set; }
public void AddEmail(EmailAddress email)
{
this.EmailAddresses.Add(email);
}
public void ChangeEmail(EmailAddress email)
{
EmailAddress orig = this.EmailAddresses.First(e => e.Id == email.id);
// update properties on orig
// NOW WHAT? [this] knows nothing about the context in order to change state,
etc, or do anything to mark the email add updated
}
}
// Email
public class EmailAddress
{
public string Email { get;set; }
public bool IsPrimary { get;set; }
}
Option 2:
Let the person service use the repository to add/update the email address and don't implement the behavior on the person entity. This is much simpler in the case of many to many relationships (for example, address, where two tables need to be updated to complete the work) but the model then becomes 'anemic' being just a bunch of getters and setters.
// Person Service
public class PersonService {
// constructor injection to get unit of work and person repository...
// ...methods to add/update a person
public EmailAddress AddEmailAddress(int personId, EmailAddress email)
{
Person p = personRepository.Find(p => p.Id == personId).First();
personRepository.AddEmail(personId, email);
uow.SaveChanges();
return email;
}
public EmailAddress ChangeEmailAddress(EmailAddress email)
{
personRepository.ChangeEmail(email);
uow.SaveChanges();
return email;
}
}
// Person Repository
public class PersonRepository
{
// generic repository implementation
}
// Person Entity
public class Person
{
public string Name { get;set; }
public IEnumerable<EmailAddress> EmailAddresses { get;set; }
}
// Email
public class EmailAddress
{
public string Email { get;set; }
public bool IsPrimary { get;set; }
}
Anyway, any thoughts on this?
Thanks, Brian
Option 1 is the way to go.
Reasoning is simple - changing e-mail addresses is domain concern. I bet Your domain experts have said that they will need to change emails. That automatically marks email changing piece of logic as business logic which is supposed to live in domain model. Objects primarily are defined by their behavior and not data that they hold.
Also - think twice before You choose to use unit of work pattern and wrap around everything in services. Aggregate roots are supposed to draw transaction boundaries and services usually are useless if they just wrap repository and domain object calls.
I would have something like this:
public class Person{
public Email Email{get;private set;}
public void SpecifyEmail(Email email){
//some validation, if necessary
EnsureEmailCanBeChanged();
//applying state changes
Email=email;
//raising event, if necessary
Raise(new EmailChanged(this));
}
public class EmailChanged:Event<Person>{
public EmailChanged(Person p):base(p){}
}
}
public class Email{
public Email(string email){
//validations (e.g. email format)
Value=email;
}
//implicit to string, explicit from string conversions
}
public class PersonController{
public ActionResult SpecifyEmail(int person, string email){
_persons.Get(person).SpecifyEmail((Email)email);
return RedirectToAction("Person",new{person});
}
}
I'm using NHibernate - it's smart enough to figure out what has changed since Person was persisted last time. Hard to say how exactly entity framework handles this.
I'm an NH user and may not know all EF limitations but generally speaking, whatever the limitations of ORM, entities should be left as clean as possible. Service Layer is already coupled with Data Access so no harm's done.
And I believe EF4 should know how to track collection changes. If not, then the best way is to leave the adding/removing logic in your Person entity and persist in PersonService.
BTW, your EmailAddress isn't an entity here, no Id (just a typo I guess). And how do you link your EmailAddress to Person?
I'm trying to get a repository pattern working with MVC2 and EF.
My problem is within the concrete repository. When I attempt to cast the EF query results as an IEnumerable collection of view-model entities:
Unable to cast object of type
'System.Data.Objects.ObjectQuery`1[Data_Service.MediaReleases]'
to type
'System.Collections.Generic.IEnumerable`1[TestMVCWithFacory.Models.Entities.MediaReleaseModel]'.
I sense that's a bone-headed thing to try to do -- and it's something with Linq, and how deferred execution works, but I don't really understand the voodoo.
So what is it that I'm mis-understanding there, and how do I address it?
The view-model:
public class MediaReleaseModel
{
public string Headline { get; set; }
public string FullText { get; set; }
}
The repository interface:
public interface IMediaReleasesRepository
{
IEnumerable<MediaReleaseModel> MediaReleases { get;}
}
The concrete repository:
public class MediaReleaseRepository : IMediaReleasesRepository
{
private NewsEntities DataContext = new NewsEntities();
private IEnumerable<MediaReleases> _MRs;
public MediaReleaseRepository()
{
_MRs = from art in DataContext.MediaReleases select art;
}
public IEnumerable<MediaReleaseModel> MediaReleases
{
get { return (IEnumerable<MediaReleaseModel>)_MRs; }
}
}
Controller:
public class HomeController : Controller
{
private IMediaReleasesRepository _MRRepository;
public HomeController()
{
_MRRepository= new MediaReleaseRepository();
}
public ViewResult index()
{
return View(_MRRepository.MediaReleases.ToList());
}
}
You're trying to cast collection of MediaReleases to collection of MediaReleaseModels. If MediaReleaseModel is a separate class, this can't be done just by casting. Generally, cast will succeed only in one inheritance chain or when conversion operators are defined, which is not the case here.
What you need here is rewriting the MediaRelease fields to you model object (it can be automated using tools like AutoMapper), i.e. with help of LINQ:
public IEnumerable<MediaReleaseModel> MediaReleases
{
get
{
return _MRs.Select(x => new MediaReleaseModel()
{
Prop1 = x.Prop1
/* etc. */
});
}
}
One suggestion at the side: it's better not to have logic like that in constructor, creating objects should be cheap operation and it's a bit strange when the data are fetched before they are really needed.
I am trying to decide on an ORM tool for my project, and I am thinking about EF4.
What are the major (if any) annoyances/limitations with this product? Also, does it support caching?
Thanks
This is a good place to start. Granted he's one of the main contributors of NHibernate so that particular post may seem a little bit biased, but there are some good links and arguments in the comments.
And looks like someone asked a very similar question on SO a few months back.
The inability to use private backing fields for lazy loading collections. For example take this class:
public class Account
{
private IList<Customer> _customers = new List<Customer>();
public IEnumerable<Customer> Customers
{
get { return _customers ; }
}
public void AddCustomer(Customer customer)
{
//Perform some biz rules
_customers.Add(customer)
}
}
Access to the customers collection is restricted by using an IEnumerable collection and having a AddCustomer / RemoveCustomer methods on the class. Typically you want to do some business checking before adding or removing a new customer.
The current version of EF requires lazy loading collection types to be ICollection (or any type that implements ICollection). So the above class now would look like:
public class Account
{
private IList<Customer> _customers = new List<Customer>();
public virtual ICollection<Customer> Customers
{
get { return _customers ; }
}
public void AddCustomer(Customer customer)
{
//Perform some biz rules
_customers.Add(customer)
}
}
Using a public ICollection Customers completely destroys good OO design principals as consumers could directly access by calling the Add Operation on ICollection.
Account acc = new Account();
acc.Customers.Add(new Customer()); //Bad code
The original intention of the domain class was to use the public add method:
Account acc = new Account();
acc.AddCustomer(new Customer());
NHibernate can handle this scenario through configuration. I would very much like to see this scenario supported in the EF.
Note however there is a workaround for the this limitation by declaring the the backing field as protected and map it through configuration:
public class Account
{
protected virtual ICollection<Customer> _customers = new Collection<Customer>();
public IEnumerable<Customer> Customers
{
get { return _customers ; }
}
public void AddCustomer(Customer customer)
{
//Perform some biz rules
_customers.Add(customer)
}
}
But this won't work if your application has a layered architecture (i.e your domain model is separated from EF configuration classes) because protected types are not accessible to external classes.
In order for this to work requires the EF classes to be in the same assembly as your domain models!
Lazing loading collections require a public or protected type that implements ICollection.