in my project ,the Business Logic all in the Application Service,Domain Service just some entity,who can tell me or give me a example to show How to Add Business Logic to the Domain Service in Domain-Driven-Design? very thanks!
UPDATE
i write a simple solutation,this solutation is a vote system,the solutation main part is:
Vote.Application.Service.VoteService.cs:
namespace Vote.Application.Service
{
public class VoteService
{
private IVoteRepository _voteRepository;
private IArticleRepository _articleRepository;
public VoteService(IVoteRepository voteRepository,IArticleRepository articleRepository)
{
_voteRepository = voteRepository;
_articleRepository = articleRepository;
}
public bool AddVote(int articleId, string ip)
{
var article = _articleRepository.Single(articleId);
if (article == null)
{
throw new Exception("this article not exist!");
}
else
{
article.VoteCount++;
}
if (IsRepeat(ip, articleId))
return false;
if (IsOvertakeTodayVoteCountLimit(ip))
return false;
_voteRepository.Add(new VoteRecord()
{
ArticleID = articleId,
IP = ip,
VoteTime = DateTime.Now
});
try
{
_voteRepository.UnitOfWork.Commit();
return true;
}
catch (Exception ex)
{
throw ex;
}
}
private bool IsRepeat(string ip, int articleId)
{
//An IP per article up to cast 1 votes
//todo
return false;
}
private bool IsOvertakeTodayVoteCountLimit(string ip)
{
//An IP per day up to cast 10 votes
//todo
return false;
}
}
}
Vote.Domain.Contract.IVoteRepository.cs:
namespace Vote.Domain.Contract
{
public interface IVoteRepository
: IRepository<VoteRecord>
{
void Add(VoteRecord model);
}
}
Vote.Domain.Contract.IArticleRepository.cs:
namespace Vote.Domain.Contract
{
public interface IArticleRepository
: IRepository<Article>
{
void Add(VoteRecord model);
Article Single(int articleId);
}
}
Vote.Domain.Entities.VoteRecord:
namespace Vote.Domain.Entities
{
public class VoteRecord
{
public int ID { get; set; }
public DateTime VoteTime { get; set; }
public int ArticleID { get; set; }
public string IP { get; set; }
}
}
Vote.Domain.Entities.Article:
namespace Vote.Domain.Entities
{
public class Article
{
public int ID { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int VoteCount { get; set; }
}
}
i want move the Business Login in application.service to Domain.service(current not this project),who can help me?how to do is reasonable? very thanks!
This is the simplest scenario. If your domain model is very simple (i.e. CRUD based), then putting the business logic directly in a transaction script or a request handler might be ok.
The domain layer is responsible for encapsulating complex business logic, or simple business logic that is reused by multiple ViewModels. This layer is optional because not all apps will have these requirements. You should only use it when needed-for example, to handle complexity or favor reusability.
Domain-driven design (DDD) is a major software design approach, focusing on modelling software to match a domain according to input from that domain's experts. Under domain-driven design, the structure and language of software code (class names, class methods, class variables) should match the business domain.
A domain model contains clusters of different data entities and processes that can control a significant area of functionality, such as order fulfillment or inventory. A more fine-grained DDD unit is the aggregate, which describes a cluster or group of entities and behaviors that can be treated as a cohesive unit.
DDD is focusing how to design domain models to fit with requirement, the schema in database does not matter much.
If your domain entity is just property bag, seems you are violating the Anemic Model anti-pattern. Business logic should be in domain entities. So, in your case, in order to avoid business logic leaking to Application service. You can have a new model called Client for example to store Ip or other properties if necessary.
To have easier understanding, whether Client exceeds the limits in day, this method should be in Client class. Similar with the method IsRepeated.
So, your domain object should be:
public class Client
{
public string Ip { get; set; }
// More properties if needed
public List<Vote> Votes { get; set; }
public bool ExceedLimitInDay()
{
}
}
public class Vote
{
public int Id { get; set; }
public DateTime VoteTime { get; set; }
public Article Article { get; set; }
public Client { get; set; }
}
public class Article
{
public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public List<Vote> Votes { get; set; }
public bool IsRepeated(string ip)
{
return Votes.Select(v => v.Client.Ip == ip).Any();
}
}
Note: If you don't need to create new table Client, just map it into Vote table. As for VoteCount properties, it is needless because you can count based on the list of Vote
I think Vote and Article are an Aggregate. I don't know much about your domain, but I assume each vote is only important to a given Article. Votes won't be shared across Articles so they should be treated as members of the aggregation, and not treated as entities of the whole domain.
In my opinion, Article would be the root entity of the Aggregate and Vote would be a member entity inside. Applying this "pattern" you could encapsulate all the business logic inside.
You could have a AddVote(...) inside your article, or some business logic like this.
Then you might be wondering.. "Ok.. but what about persistance??". Since you are defining your Article-Vote as an Aggregate, you then would treat them together. If you perform CRUD operations to an Article, at the same time you will be performing these operations in their Aggregate members (votes). So you might need a repository for the ArticleAggregate, it will take care of article's votes.
Hope this make sense to you. Choose the best option depending on your domain.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With