Using factory pattern for modeling similar subscriptions - domain-driven-design

I have the following question that's been nagging at me for quite some time.
I'd like to model the following domain entity "Contact":
public class Contact:IEntity<Contact>
{
private readonly ContactId _Id;
public ContactId Id
{
get { return this._Id; }
}
private CoreAddress _CoreAddress;
public CoreAddress CoreAddress
{
get { return this._CoreAddress; }
set
{
if (value == null)
throw new ArgumentNullException("CoreAddress");
this._CoreAddress = value;
}
}
private ExtendedAddress _ExtendedAddress;
public ExtendedAddress ExtendedAddress
{
get { return this._ExtendedAddress; }
set
{
if (value == null)
throw new ArgumentNullException("ExtendedAddress");
this._ExtendedAddress = value;
}
}
private readonly IList<ContactExchangeSubscription> _Subscriptions
= new List<ContactExchangeSubscription>();
public IEnumerable<ContactExchangeSubscription> Subscriptions
{
get { return this._Subscriptions; }
}
public Contact(ContactId Id, CoreAddress CoreAddress, ExtendedAddress ExtendedAddress)
{
Validations.Validate.NotNull(Id);
this._Id = Id;
this._CoreAddress = CoreAddress;
this._ExtendedAddress = ExtendedAddress;
}
}
As you can see it has a collection of subscriptions. A subscription is modeled like this:
public class ContactExchangeSubscription
{
private ContactId _AssignedContact;
public ContactId AssignedContact
{
get { return this._AssignedContact; }
set
{
if (value == null)
throw new ArgumentNullException("AssignedContact");
this._AssignedContact = value;
}
}
private User _User;
public User User
{
get { return this._User; }
set
{
Validations.Validate.NotNull(value, "User");
this._User = value;
}
}
private ExchangeEntryId _EntryId;
public ExchangeEntryId EntryId
{
get { return this._EntryId; }
set
{
if (value == null)
throw new ArgumentNullException("EntryId");
this._EntryId = value;
}
}
public ContactExchangeSubscription(ContactId AssignedContact, User User, ExchangeEntryId EntryId)
{
this._AssignedContact = AssignedContact;
this._User = User;
this._EntryId = EntryId;
}
}
Now I've been thinking that I shouldnt model a storage technology (Exchange) in my domain, after all, we might want to switch our application to other subscription providers. The property "EntryId" is specific to Exchange. A subscription would always need a User and a ContactId, though.
Is there a better way to model the Subscription? Should I use a factory or abstract factory for the Subscription type to cover other types of subscriptions, should the need arise?
EDIT: So let's toss an abstract factory in the ring and introduce some interfaces:
public interface IContactSubscriptionFactory
{
IContactSubscription Create();
}
public interface IContactSubscription
{
ContactId AssignedContact { get;}
User User { get; }
}
How would a concrete factory for a ContactExchangeSubscription be coded? Remember that this type will need the EntryID field, so it has to get an additional ctr parameter. How to handle different constructor paremeters on different sub-types in factories in general?

I think the answer is staring you in the face in that you need to work against an interface making it easier to introduce new subscription providers (if that's the right term) in the future. I think this is more of an OO design question that DDD.
public interface ISubscriptionProvider
{
ContactId AssignedContact { get; }
User User { get; }
}
And the code in your contract becomes
private readonly IList<ISubscriptionProvider> _subscriptions
= new List<ISubscriptionProvider>();
public IEnumerable<ISubscriptionProvider> Subscriptions
{
get { return _subscriptions; }
}
With regards to using a factory; the purpose of a factory is to construct your domain objects when a creation strategy is required. For example a SubscriptionProviderFactory could be used within your repository when you rehydrate your aggregate and would make the decision to return the ContactExchangeSubscription (as an ISubscriptionProvider) or something else based on the data passed into it.
One final point but perhaps this is just because of the way you have shown your example. But I would say your not really following DDD, the lack of behaviour and with all your propeties having public getters and setters, suggestions your falling into the trap of building an Aemic Domain Model.

After some research I came up with this. Code first, explanation below:
public interface IContactFactory<TSubscription> where TSubscription : IContactSubscription
{
Contact Create(ContactId Id, CoreAddress CoreAddress, ExtendedAddress ExtendedAddress, TSubscription Subscription);
}
public class ContactFromExchangeFactory : IContactFactory<ContactExchangeSubscription>
{
public Contact Create(ContactId Id, CoreAddress CoreAddress, ExtendedAddress ExtendedAddress, ContactExchangeSubscription ExchangeSubscription)
{
Contact c = new Contact(Id, CoreAddress, ExtendedAddress);
c.AddSubscription(ExchangeSubscription);
return c;
}
}
I realized that I dont need a factory for the Contactsubscription but rather for the contact itself.
I learned some things about factories along the way:
They are only to be used when creating (really) new entities, not when rebuilding them from a SQL DB for example
They live in the domain layer (see above!)
Factories are more suitable for similar objects that differ in behaviour rather than data
I welcome comments and better answers.

Related

DDD entity with complex creation process

How entities with complex creation process should be created in DDD? Example:
Entity
- Property 1
- Property 2: value depends on what was provided in Property 1
- Property 3: value depends on what was provided in Property 1
- Property 4: value depends on what was provided in Property 1, 2 and 3
I have two ideas but both looks terrible:
Create entity with invalid state
Move creation process to service
We are using REST API so in first scenario we will have to persist entity with invalid state and in second scenario we move logic outside of the entity.
You can use the Builder Pattern to solve this problem.
You can make a Builder that has the logic for the dependencies between properties and raise Exceptions, return errors or has a mechanism to tell the client which are the next valid steps.
If you are using an object orienterd language, the builder can also return different concrete classes based on the combination of these properties.
Here's a very simplified example. We will store a configuration for EventNotifications that can either listen on some Endpoint (IP, port) or poll.
enum Mode { None, Poll, ListenOnEndpoint }
public class EventListenerNotification {
public Mode Mode { get; set; }
public Interval PollInterval { get; set; }
public Endpoint Endpoint { get; set; }
}
public class Builder {
private Mode mMode = Mode.None;
private Interenal mInterval;
private Endpoint mEndpoint;
public Builder WithMode(Mode mode) {
this.mMode = mode;
return this;
}
public Builder WithInterval(Interval interval) {
VerifyModeIsSet();
verifyModeIsPoll();
this.mInterval = interval;
return this;
}
public Builder WithEndpoint(Endpoint endpoint) {
VerifyModeIsSet();
verifyModeIsListenOnEndpoint();
this.mInterval = interval;
return this;
}
public EventListenerNotification Build() {
VerifyState();
var entity = new EventListenerNotification();
entity.Mode = this.mMode;
entity.Interval = this.mInterval;
entity.Endpoint = this.mEndpoint;
return entity;
}
private void VerifyModeIsSet() {
if(this.mMode == Mode.None) {
throw new InvalidModeException("Set mode first");
}
}
private void VerifyModeIsPoll() {
if(this.mMode != Mode.Poll) {
throw new InvalidModeException("Mode should be poll");
}
}
private void VerifyModeIsListenForEvents() {
if(this.mMode != Mode.ListenForEvents) {
throw new InvalidModeException("Mode should be ListenForEvents");
}
}
private void VerifyState() {
// validate properties based on Mode
if(this.mMode == Mode.Poll) {
// validate interval
}
if(this.mMode == Mode.ListenForEvents) {
// validate Endpoint
}
}
}
enum BuildStatus { NotStarted, InProgress, Errored, Finished }
public class BuilderWithStatus {
private readonly List<Error> mErrors = new List<Error>();
public BuildStatus Status { get; private set; }
public IReadOnlyList<Error> Errors { get { return mErrors; } }
public BuilderWithStatus WithInterval(Interval inerval) {
if(this.mMode != Mode.Poll) {
this.mErrors.add(new Error("Mode should be poll");
this.Status = BuildStatus.Errored;
}
else {
this.mInterval = interval;
}
return this;
}
// rest is same as above, but instead of throwing errors you can record the error
// and set a status
}
Here are some resources with more information and other machisms that you can use:
https://martinfowler.com/articles/replaceThrowWithNotification.html
https://martinfowler.com/eaaDev/Notification.html
https://martinfowler.com/bliki/ContextualValidation.html
Take a look at chapter 6 of the Evans book, which specifically talks about the life cycle of entities in the domain model
Creation is usually handled with a factory, which is to say a function that accepts data as input and returns a reference to an entity.
in second scenario we move logic outside of the entity.
The simplest answer is for the "factory" to be some method associate with the entity's class - ie, the constructor, or some other static method that is still part of the definition of the entity in the domain model.
But problem is that creation of the entity requires several steps.
OK, so what you have is a protocol, which is to say a state machine, where you collect information from the outside world, and eventually emit a new entity.
The instance of the state machine, with the data that it has collected, is also an entity.
For example, creating an actionable order might require a list of items, and shipping addresses, and billing information. But we don't necessarily need to collect all of that information at the same time - we can get a little bit now, and remember it, and then later when we have all of the information, we emit the submitted order.
It may take some care with the domain language to distinguish the tracking entity from the finished entity (which itself is probably an input to another state machine....)

Factory pattern in DDD

Which is correct or suggested way to use factories in DDD?
Should factory method receive all necessary parameters from application service, or we are allowed to inject repositories and extract needed data inside factory?
Should it be (example 1):
public class UserTokenFactory : IUserTokenFactory
{
IUserTypeResourceRepository _userTypeResourceRepository;
public UserTokenFactory(IUserTypeResourceRepository userTypeResourceRepository)
{
_userTypeResourceRepository = userTypeResourceRepository;
}
public async Task<UserToken> CreateWithAsync(User user)
{
var userTypeResources = await _userTypeResourceRepository.GetByUserTypeIdAsync(user.UserTypeId);
//Some logic for creating user tokens
throw new NotImplementedException();
}
}
or as (Example 2)
public class UserTokenFactory : IUserTokenFactory
{
IUserTypeResourceRepository _userTypeResourceRepository;
public UserTokenFactory(IUserTypeResourceRepository userTypeResourceRepository)
{
_userTypeResourceRepository = userTypeResourceRepository;
}
public UserToken CreateWith(User user, List<UserTypeResource> userTypeResources)
{
//Some logic for creating user tokens
throw new NotImplementedException();
}
}
You are allowed to inject services into factories. Your factory is basically a domain service which happens to create objects. However, I'd probably rely on the ISP here and define an interface like IResolveUserType rather than depending on the wider IUserTypeResourceRepository interface.

Is WCF Service EntitySetRights.AllRead Secure?

I have the following code inside MyDataService.svc.cs (This is an example from DevExpress):
namespace MyDataService {
[System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)]
[JSONPSupportBehavior]
public class DataService : DataService<TestDataEntities>, IServiceProvider {
public static void InitializeService(DataServiceConfiguration config) {
config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;
}
public object GetService(Type serviceType) {
if (serviceType == typeof(IDataServiceStreamProvider)) {
return new ImageStreamProvider();
}
return null;
}
protected override void OnStartProcessingRequest(ProcessRequestArgs args) {
CustomBasicAuth.Authenticate(HttpContext.Current);
if (HttpContext.Current.User == null)
throw new DataServiceException(401, "Invalid login or password");
base.OnStartProcessingRequest(args);
}
}
}
So while this is will check the Entity for a username and password, how safe is it that config.SetEntitySetAccessRule is set to AllRead. Wouldn't someone just be able to see this information on a url such as www.website.com/MyDataService.svc/Customer (where Customer is the table). If this is not so can someone please fill in the conceptual gap I am facing. Thanks!
You are correct that all entities will be returned when queried - AllRead just disallows insert updates and deletes.
You will need to use Query Interceptor to add your logic to restrict users to the set of data they have permission to view, for example adding a check user id to the query.

Assigning an async result to a data binding property

Below is a sample implementation that uses metro API and data binding (using MVVM) to populate list of folders in a drop down list.
The View model‘s constructor uses SetFolders method (private async), which calls an awaitable method fileService.GetFoldersAsync() to get list of folders. The folders list is then gets assigned to the property called “FoldersList”. XAML uses this property to populate a drop down list using the data binding.
I wonder is there a better way to set the FoldersList property without having to set it in the constructor as below. I would prefer to call the GetFilesAsync method and set the FilesList property value, when the actual data binding occurs (not during the class init). Since the properties do not support async/await modifiers (as far as I know) I’m struggling to implement a proper solution. Any ideas greatly appreciated.
The code is below.
ViewModel
public class FileViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private readonly IFileService fileService;
public FileDataViewModel(IFileService fileService)
{
this.fileService = fileService;
SetFolders();
}
private async void SetFolders ()
{
FoldersList = await fileService.GetFoldersAsync();
}
private IEnumerable< IStorageFolder > foldersList;
public IEnumerable<StorageFolder> FoldersList
{
get { return foldersList; }
private set
{
foldersList = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("FoldersList"));
}
}
}
}
IFileService and implementation
public interface IFileService {
Task<IEnumerable<IStorageFolder>> GetFilesAsync();
}
public class FileService : IFileService
{
public async Task<IEnumerable<IStorageFolder>> GetFoldersAsync()
{
var folder = KnownFolders.DocumentsLibrary;
return await folder.GetFoldersAsync();
}
}
I would implement it as a lazy property and use ObservableCollection<T> rather than IEnumerable<T>. We are doing it in several projects and it works well. This way you can guarantee that you are loading data only when needed. Furthermore, if you need to prefetch it, you can always call the load method in the constructor or elsewhere.
As a side note, I personnaly wouldn't expose IStorageFolder directly from my ViewModels.
private async Task LoadData()
{
if(!IsLoading)
{
IsLoading = true;
Folders = new ObservableCollection<Folder>(await fileService.GetFolderAsync());
}
IsLoading = false;
}
private ObservableCollection<Folder> _folders;
public ObservableCollection<Folder> Folders
{
get
{
if(_folders == null)
{
LoadData();//Don't await...
}
return _folders;
}
private set
{
SetProperty(ref _folders,value);
}
}
private bool _isLoading;
public bool IsLoading
{
get
{
return _isLoading;
}
private set
{
SetProperty(ref _isLoading,value);
}
}
Note that you can use the IsLoading property to display a progress ring for instance. after that the observable collection is loaded, you will be able to refresh it without recreating it. (_folders.Add, _folders.Remove, _folders.Clear...)

How do I prevent duplicate entries using the UnitOfWork pattern with code first Entity Framework?

I am using the Unit of Work and Generic Repository pattern. Here is the statement that checks for a duplicate entry:
int id = int.Parse(beer.id); //id comes from the item we're hoping to insert
if (_unitOfWork.BeerRepository.GetByID(id) == null)
\\create a new model br
_unitOfWork.BeerRepository.Insert(br);
_unitOfWork.save();
Apparently this is failing to check to see if the beer is already in the database because I get this inner exception:
Violation of PRIMARY KEY constraint 'PK_Beers_3214EC2703317E3D'.
Cannot insert duplicate key in object 'dbo.Beers'.\r\nThe statement
has been terminated.
I also get this message:
An error occurred while saving entities that do not expose foreign
key properties for their relationships. The EntityEntries property
will return null because a single entity cannot be identified as the
source of the exception. Handling of exceptions while saving can be
made easier by exposing foreign key properties in your entity types.
See the InnerException for details.
The UnitOfWork class has my BeerRecommenderContext which implements DbContext and the UnitOfWork has a generic repository for each entity:
namespace BeerRecommender.Models
{
public class GenericRepository<TEntity> where TEntity : class
{
internal BeerRecommenderContext context;
internal DbSet<TEntity> dbSet;
public GenericRepository(BeerRecommenderContext context)
{
this.context = context;
this.dbSet = context.Set<TEntity>();
}
public virtual IEnumerable<TEntity> Get(
Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = "")
{
IQueryable<TEntity> query = dbSet;
if (filter != null)
{
query = query.Where(filter);
}
foreach (var includeProperty in includeProperties.Split
(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(includeProperty);
}
if (orderBy != null)
{
return orderBy(query).ToList();
}
else
{
return query.ToList();
}
}
public virtual TEntity GetByID(object id)
{
return dbSet.Find(id);
}
public virtual void Insert(TEntity entity)
{
dbSet.Add(entity);
}
public virtual void Delete(object id)
{
TEntity entityToDelete = dbSet.Find(id);
Delete(entityToDelete);
}
public virtual void Delete(TEntity entityToDelete)
{
if (context.Entry(entityToDelete).State == EntityState.Detached)
{
dbSet.Attach(entityToDelete);
}
dbSet.Remove(entityToDelete);
}
public virtual void Update(TEntity entityToUpdate)
{
dbSet.Attach(entityToUpdate);
context.Entry(entityToUpdate).State = EntityState.Modified;
}
}
}
I have a similar usage of repository using code-first. Occasionally, I would see conflicts like the one you described. My issue was with change tracking across multiple processes. Are you inserting items into the database inside one process (using a single entity context)?
If you are, you should look at the Merge Options available with Entity Framework. If you are using the default merge option (AppendOnly), then you could be querying the in memory context instead of going to the database. This could cause the behaviour you are describing.
Unfortunately, as far as I understand, all the merge options are not yet exposed to Code-First. You can choose the default (AppendOnly) or NoTracking, which will go to the database every time.
Hope this helps,
Davin

Resources