<<ABP Framework >> Field Services

Source: Internet
Author: User
Tags app service in domain to domain

Document Directory

The content of this section:

    • Brief introduction
    • Example
      • Create an interface
      • Implementation services
      • Using app Service
    • Related discussion
      • Why not just use app service?
      • How do I force you to use Domain Services?

Brief introduction

Domain Services (or services) are used to perform domain operations and business rules. Eric Evans describes a good service that requires three features (in his DDD book):

    1. Operations are related to domain concepts (not a natural part of an entity or value object).
    2. Interfaces are defined in terms of other domain model elements.
    3. The operation is stateless.

Unlike the app service get/return DTO (data transfer object), the domain service gets/Returns a domain object (such as an entity or value type).

Domain Services can be invoked by application services or other domain Services, but are not directly used by the presentation layer (application service is for it).

Idomainservice Interface and Domainservice services

The ABP defines the Idomainservice interface, which is implemented by all Domain Services as agreed, and Domain Services are automatically temporarily registered to the dependency injection system after implementation.

Similarly, Domain Services (optionally) can inherit from the Domainservice class, so it can use inherited logs, localization, and other attributes. Even if you do not inherit the Domainservice class, you can inject it when you need it.

Example

Suppose we have a task management system and a business rule that assigns tasks to people.

Create an interface

First, we define an interface for the service (not required, but a good practice):

 Public Interface  idomainservice{    void  Assigntasktoperson (Task task, person person);}

As you can see, the TaskManager service uses the domain object: a task and a person. Naming Domain Services have some conventions that can be named: TaskManager, Taskservice, or taskdomainservice ...

Implementation services

Let's take a look at the implementation:

 Public classTaskManager: DomainService, itaskmanager{ Public Const intMaxactivetaskcountforaperson =3; Private ReadOnlyitaskrepository _taskrepository;  PublicTaskManager (itaskrepository taskrepository) {_taskrepository=taskrepository; }     Public voidAssigntasktoperson (Task task, person person) {if(Task. Assignedpersonid = =Person . Id) {return; }        if(Task. State! =taskstate.active) {Throw NewApplicationException ("Can not assign a task to a person when task is not active!"); }        if(Haspersonmaximumassignedtask (person)) {Throw NewUserfriendlyexception (L ("Maxpersontasklimitmessage", person.        Name)); } task. Assignedpersonid=Person .    Id; }    Private BOOLhaspersonmaximumassignedtask (person person) {varAssignedtaskcount = _taskrepository.count (t = t.state = = Taskstate.active && T.assignedpersonid = =Person .        ID); returnAssignedtaskcount >=Maxactivetaskcountforaperson; }}

Here we have two business rules:

    • A task should be active in order to be assigned to a new person.
    • A person can allocate up to 3 active tasks

You might wonder why I throw a applicationexception in the first check, throw userfriendlyexception in the second check (see Exception handling), which is irrelevant to the domain service, and I'm just going to give you an example Exactly what to do is up to you. I think that the user interface must check the status of a task and should not be assigned to a person, which I think is an application error and should be hidden from the user. The second is a check on the UI, and we display a readable error message to the user.

Using app Service

Now, let's take a look at how an app service uses the TaskManager service:

 Public classTaskappservice:applicationservice, itaskappservice{Private ReadOnlyIrepository<task,Long>_taskrepository; Private ReadOnlyIrepository<person>_personrepository;  Private readonly  itaskmanager _taskmanager;      PublicTaskappservice (Irepository<task,Long> Taskrepository, irepository<person>personrepository, itaskmanager taskmanager) {_taskrepository=taskrepository; _personrepository=personrepository; _taskmanager=TaskManager; }     Public voidAssigntasktoperson (Assigntasktopersoninput input) {varTask =_taskrepository.get (input.        TASKID); varperson =_personrepository.get (input.        PERSONID);    _taskmanager.assigntasktoperson (task, person); }}

Taskapplicationservice uses the given DTO (input) and warehousing to get the relevant task and person, and then passes them to the TaskManager (domain service).

Related discussion

According to the above example, you may have some questions to ask.

why not just use app service ?

Which is why application services do not implement business logic in Domain Services?

We can simply say that it is not an application service task, because it is not a use case, but a business operation. We may use the same domain logic for "Assigning tasks to people" in another use case, for example: We update the task in some way on another interface, which includes assigning tasks to another person; we may have two different UI (a mobile app and a web app) sharing the same domain , or a Web API that provides remote clients with assignment task operations.

If your domain is simple, there is only one UI and only one place to assign tasks to people, you may want to skip Domain Services and implement business logic directly in your app service, which is not a best practice for ddd, but ABP does not enforce that you cannot use this design.

How do I force you to use Domain Services?

The app service can do this simply:

 Public void Assigntasktoperson (Assigntasktopersoninput input) {    var task = _taskrepository.get (input. TASKID);      =   input. PersonId;}

Developers who write application services may not know the existence of TaskManager, directly assign a given personid to Assignedpersonid, so how do you stop it?

There is a lot of discussion about this problem in the DDD field, there are some usage patterns, we are not ready to go very deep, but we provide a simple way:

We modify the task entity to resemble the following:

 Public classtask:entity<Long>{     Public Virtual int? Assignedpersonid {Get; protected set ; } //... other members and codes of Task entityPublic   void  Assigntoperson (person person, Itaskpolicy Taskpolicy) {Taskpolicy.checkif Canassigntasktoperson (this, person); Assignedpersonid = Person  .    Id; }}

We have modified the Assignedpersonid to protected so that it cannot be modified outside the entity class. Add a Assigntoperson method that accepts a person and a taskpolicy. The Checkifcanassigntasktoperson method checks to see if it can be allocated and throws a corresponding exception when it cannot be allocated (it does not matter how it is implemented here). Then the app service looks like this:

 Public void Assigntasktoperson (Assigntasktopersoninput input) {    var task = _taskrepository.get (input. TASKID);     var person = _personrepository.get (input. PERSONID);    task. Assigntoperson (person, _taskpolicy);}

We inject the _taskpolicy into the itaskpolicy and pass it to the Assigntoperson method. At this point there is no second way to assign a task to a person, we can only use Assigntoperson, no longer jump business rules.

<<ABP Framework >> Field Services

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.