Skip to content

Instantly share code, notes, and snippets.

@phillippelevidad
Last active October 19, 2018 17:25
Show Gist options
  • Save phillippelevidad/9fc0353b0761519558ee770ca4451a41 to your computer and use it in GitHub Desktop.
Save phillippelevidad/9fc0353b0761519558ee770ca4451a41 to your computer and use it in GitHub Desktop.
User Voice DDD - domain implementation
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace UserVoiceFun.Domain
{
public abstract class Entity
{
public Guid Id { get; protected set; } = Guid.NewGuid();
}
public class User : Entity // Aggregate Root
{
public string Key => $"{Email}:{MarketplaceUrl}";
public string Name { get; }
public string Email { get; }
public string MarketplaceName { get; }
public Uri MarketplaceUrl { get; }
internal User(string name, string email, string marketplaceName, Uri marketplaceUrl)
{
Name = name;
Email = email;
MarketplaceName = marketplaceName;
MarketplaceUrl = marketplaceUrl;
}
public Suggestion MakeSuggestion(string text)
{
return new Suggestion(Id, text);
}
}
public class Suggestion : Entity // Aggregate Root
{
public string Text { get; /* a suggestion cannot be altered */ }
public Guid ByUserId { get; }
public DateTime SuggestedAt { get; }
public ICollection<Comment> Comments { get; } = new List<Comment>();
public ICollection<Vote> Votes { get; } = new List<Vote>();
internal Suggestion(Guid byUserId, string text)
{
ByUserId = byUserId;
Text = text;
SuggestedAt = DateTime.UtcNow;
}
public Comment AddComment(Guid byUserId, string text)
{
var comment = new Comment(byUserId, text);
Comments.Add(comment);
return comment;
}
public void RemoveComment(Comment comment, Guid userIdRemovingComment)
{
if (comment.ByUserId != userIdRemovingComment)
throw new CannotRemoveCommentFromAnotherUserException();
Comments.Remove(comment);
}
public void Unvote(Guid byUserId)
{
var vote = Votes.SingleOrDefault(v => v.ByUserId == byUserId);
if (vote != null)
Votes.Remove(vote);
}
public Vote Vote(Guid byUserId)
{
if (Votes.Any(v => v.ByUserId == byUserId))
throw new CannotVoteTwiceOnSameSuggestionException();
var vote = new Vote(byUserId);
Votes.Add(vote);
return vote;
}
}
public class Comment : Entity
{
public string Text { get; /* a comment cannot be changed */ }
public Guid ByUserId { get; }
public DateTime CommentedAt { get; }
internal Comment(Guid byUserId, string text)
{
ByUserId = byUserId;
Text = text;
CommentedAt = DateTime.UtcNow;
}
}
public class Vote : Entity
{
public Guid ByUserId { get; }
public DateTime VotedAt { get; }
internal Vote(Guid byUserId)
{
ByUserId = byUserId;
VotedAt = DateTime.UtcNow;
}
}
public interface IUsersStore
{
Task AddUserAsync(User user);
Task<User> GetUserAsync(Guid id);
}
public interface ISuggestionsStore
{
Task AddSuggestionAsync(Suggestion suggestion);
Task<Suggestion> GetSuggestionAsync(Guid id);
// For when comments and votes are added/removed to/from a suggestion.
Task UpdateSuggestionAsync(Suggestion suggestion);
}
public class UserVoiceService
{
private readonly IUsersStore usersStore;
public UserVoiceService(IUsersStore usersStore)
{
this.usersStore = usersStore;
}
public async Task<User> RegisterUserAsync(string name, string email, string marketplaceName, Uri marketplaceUrl)
{
var user = new User(name, email, marketplaceName, marketplaceUrl);
await usersStore.AddUserAsync(user);
return user;
}
}
public class CannotVoteTwiceOnSameSuggestionException : Exception { }
public class CannotRemoveCommentFromAnotherUserException : Exception { }
}
@phillippelevidad
Copy link
Author

A request for reviewing this model was posted to Code Review at Stack Exchange. Since then, this gist has been updated to reflect the accepted suggestions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment