I have an object called StyleBundle.
public class StyleBundle
{
public StylePricingType StylePricingType { get; private set;}
public decimal Price {get; private set;}
public IEnumerable<Style> Styles { get; set;}
public DateTime StartDate {get; private set;}
public TimeSpan Duration {get; private set;}
public bool IsTransient {get; set;}
public void ChangeStylePricingType(StylePricingType newStylePricingType)
{
this.StylePricingType = newStylePricingType;
}
}
This StyleBundle object has a property called StylePricingType. The StylePricingType is an enum of two types:
PerStyle
Unlimited
The StylePricingType will effect the overall Price of the StyleBundle. The way it will affect the Price is by changing the Styles kept in the Styles list. An Unlimited StyleBundle will automatically include all available Styles, but a PerStyle StyleBundle will allow a user to manually pick which Styles they want to include.
I now need to allow the StylePricingType to be changed if the StyleBundle is transient (previous rules stated that once a StyleBundle is new'ed up, you can not change the StylePricingType).
BUT, in order to make this change, I need to run a check against the database via a repository/specification/service... aka, however I want to do it.
The check basically looks for any other StyleBundles during the same duration of the current StyleBundle, and makes sure there are no overlap in Styles in the StyleBundle.
Since changing this property on a transient StyleBundle requires a check against other persisted StyleBundles, what is the best way to go about implementing this?
Use Constructor injection: inject a service into the StyleBundle entity's constructor. I don't like this, b/c I don't like injecting dependencies into my entities unless I need to do so. Also, since I don't like the idea of injecting the dependency into the constructor when it's only needed for the method call that will change the StylePricingType, I see this as bad design.
Use Method injection: Since I would only need the service for this one method call, this seems to make more sense. Yet at the same time, I don't like the idea the user being able to change this type without knowing they're running a db query. Also, I'm still injecting a service into my entity, just in a different way, and I really do not like injecting anything into my entities.
Use a Domain Service: this seems to be the most explicit of all. I could create a StyleBundleService class that has a ChangeStylePricingType method that uses a repository or specification to run the check given a StyleBundle. This way, the requirement is made very explicit in the code, but the drawback here is code could still call the ChangeStylePricingType method directly on the StyleBundle object, and BYPASS the ChangeStylePricingType method on the service I need to make. Even if I set the StylePricingType to get;set; instead of private set; and got rid of the ChangeStylePricingType method on StyleBundle, code could still make the change, bypassing the domain service.
So, these all seem like legitimate ways to go about doing something like this, so what is the best/most accepted way of doing it using DDD? Also, maybe my StyleBundle object is trying to do too much, and should be broken into smaller classes/functionality that would allow this requirement change to be handled more eloquently?
Mike