How to use domain-driven design - entities

Original: how to use domain-driven design - entities

Outline

This article will introduce another common and very important concept Domain Driven Design (DDD) tactical mode - entity. Relatively few tactical modes other concepts (such as value objects, field service, etc.), the entity should be relatively easy to understand and use. But how to find areas where the entities it? How to ensure the establishment of an entity is rich in action? When there are those entities using the attention to the details of it? This article from different angles to bring you new understanding about the concept of "entity", and gives the corresponding code fragment (code snippets in this tutorial are using C # , the latter part of the actual project is also based DotNet Core platform).

What is the entity

According to international practice, let's bragging. Directly look at the original "Domain-Driven Design: Coping core of software complexity Road" in the interpretation of entities:

  • Entity (Entity, also known as the Reference Object) Many objects are not defined by their attributes, but through a series of successive events and defined identity.
  • Defined mainly by the object identification is referred ENTITY.

The above two sentences to read several times, as if this definition was understandable thing. Unlike the previous article how to use DDD - Value Objects concept of so esoteric. To put it plainly, the above is to explain a problem, as long as what you found / object has a unique identifier, then it is probably the entity. The unique identification code that we write fast rotten that ID.

Deja vu

To think about, we are in the traditional design ideas and the development process, we will be given an ID it as an object under what circumstances? It gives the effect of ID it? In general our aim is nothing more than 1, in order to distinguish this object if it is in the database, that is to distinguish between data and another one of this section data, and this ID as the primary key and often there are two, plus index it, to improve Find related speed. If we are to map database tables to our code when presented in the form of classes, it probably looks like this:

//旅行的行程
public class Itinerary
{
    public int ID { get; set; }

    //参加本次旅行的人员
    public List<Person> Participants { get; set; }

    //旅行的地点
    public List<string> Places { get; set; } 

    //关于该行程的备注笔记信息
    public string  Note { get; set; } 

    //旅行开始时间
    public DateTime StartTime { get; set; }

    //旅行开始时间
    public DateTime? EndTime { get; set; }

    //旅行的状态(进行中 or 已完成)
    public int Status { get; set; }
}

The above code did for us should not unfamiliar, we have established a travel itinerary of the class, as to why we selected travel itinerary, not individual blog appear in the order ah electronic business platform as a case. That's because we will later in hands together to implement a travel journal WeChat small program, and the aid we slowly learned to DDD theory as a basis for developing our own domain-driven framework, of course, the project is also based DotNet Core (version should be 3.x).

Well, or return to our example, and think about the purpose of ID appears. You might say: "This is not simple yet old lady crossbar source world for many years, you still ask me this question ID must be used to distinguish the way, travel hundreds of thousands, I would definitely find this a stroke?! need this ID ah. "Yes, this is a undisputed issue. We need a unique identity to distinguish the differences between objects. This is usually in contact with our class ID DDD in entities with the same purpose, so the beginning of this article also said that the entity may be relative to other tactical concept most people understand.

Are you sure that you really need ID

Remember our article on how to use DDD - Value Objects a problem as you mentioned? "Current context value of the object may be another entity context." So, you have to determine the current entity must be based on the current field of environment (context) of . After leaving the environment, everything will be variable. The same things (objects), in the current environment requires a unique identifier to identify it, and in another environment that may uniquely identify it is not meaningful, the entity is likely to become a target value. Consider the following example:

In a banking application, a customer could put $ 10 in her bank account. One day when she future she extracted the $ 100, compared to her money in the bank, she may receive different bills or coins. However, this difference is irrelevant, because the identity of the funds is not important; the customer only interested in value for money. Therefore, in this field, funding is undoubtedly a value object. But in other areas, such as production or involving banknote printing banknotes traceability industry, the identity of the individual bank notes or coins may actually be an important concept is the field. So each note will be a unique entity identifier has

Application entity

Combined value of the object

Do not forget the last chapter we learned the value of the object to: the internal entities, in addition to its own unique identification ID, maybe there are many things that it attributes, and these things tend to be through the use of the value of the object is identified.
Next, let's look at rewriting the above Itinerary categories:

public class Itinerary
{
    public int ID { get; set; }

    public List<Person> Participants { get; set; }

    public List<Address> Places { get; set; } 

    public ItineraryNote  Note { get; set; } 

    public ItineraryTime TripTime { get; set; }

    public ItineraryStatus Status { get; set; }
}

public class ItineraryNote
{
    public string Content { get; set; }
    public DateTime NoteTime { get; set; }

    public ItineraryNote(string content)
    {
        Content = content;
        NoteTime = DateTime.Now;
    }
}

Entity given its behavior

When an object is set up, in order to achieve our business logic processing, we need to operate on the instantiated objects. Now we propose the first requirement for the system: Users can modify the remarks information itinerary.
Going back to our first edition of the code, if we need to deal with this operation, how would we do it?

itineraryInstance.Note = "this is my new note info";

Is the value assigned to instantiate the object is not like this above, you will need to add it. This operation, we are now going to programming practice, it is more normal.

So we have to think that if our project with multiple needs of the "Remarks information" to deal with it. The change of the property will be scattered throughout the code. And when we had an enhanced verification of the requirements, such as at this time we need to add: the user to modify information Remarks trip time, only allows users to enter text within 200 words. OMG, this time we need to find all the scattered fragments, and add validation for him.

From another perspective, a first version of the class we build, we can not only see it by itself will be able to read about the travel itinerary-related business, we only know that it has a start time, notes and other information, while no way to know how they should interact.
Therefore, this class has only attributes, or to type POCO presented, which we call "anemic model" .

Next, we go back to the second edition of the code, we give it the behavior belongs to it. We learned from the demand, notes the information itinerary can be modified, and remarks information is part of the trip, so modify the remarks information to change behavior should belong to the trip itself. We slightly change the code:

public class Itinerary
{
    public int ID { get; set; }

    public List<Person> Participants { get; set; }

    public List<Address> Places { get; set; } 

    public ItineraryNote  Note { get; set; } 

    public ItineraryTime TripTime { get; set; }

    public ItineraryStatus Status { get; set; }

    //ctor

    public void ChangeNote(string content)
    {
        if(content.Length > 200 )
            throw new NoteIsOverlengthException();
        Note  = new ItineraryNote(content);
    }
}

At this point we Itinerary gives a ChangeNote when the behavior, when the outside world needs to change notes, simply by calling either method change, but when you expand other developers to read these, will clearly understand, allow business Notes users to change 200 words or less.

However, we still have a fly in the ointment, I thought you might also find: Properties and externally exposed! Yes, that is to say, in addition to our own properties by modifying class class public behavior, we also free to change in the outside world. This obviously does not meet our design in mind. So we can set all the attributes of privatization. Therefore, we must note that we consider an entity, be sure to know that " entities within a high degree of cohesion and autonomy " (emphasis knock !!!!!).

Of course, some developers will try another wording, so that the entity full autonomy, the above code in the property, all transformed into private fields outside world can only be processed by public entities behavior.

public class Itinerary
{
    public int ID { get; set; }

    private List<Person> participants;

    private List<Address> places;

    private ItineraryNote  note;

    private ItineraryTime tripTime;

    private ItineraryStatus status;

    //ctor

    public void ChangeNote(string content)
    {
        if(content.Length > 200 )
            throw new NoteIsOverlengthException();
        note  = new ItineraryNote(content);
    }
}

But when the outside world need to get the value of the entity, or when you need ORM mapping may not very friendly, but you can use like a similar memo mode snapshot method to deal with. Late we will adopt this model to achieve some cases.

Established by the entity gives out its application behavior entity we call "congestion model." So anemic model good or congestion model is good ? Many students would certainly say, you have to ask you, is certainly congestion model friends. In fact, this answer does not have a real answer, the entity's own behavior through the analysis of the areas we slowly (probably by communicating with experts in the field) can be accomplished, if in order to use congestion as model and blind not belong to some entity behavior assigned to it, will only make the entity becomes more chaotic and thus more harm than good. So, this model does not mean that anemia has been a model of anemia, the latter with the depth of field it may belong to constantly enrich their own behavior.

Behavior to try to transfer some value objects

Keep the focus on the identity of the entity that responsibility is important because it will prevent them from becoming bloated ---- this is that they will be pulled together a number of related behaviors when easy to fall into the trap. To achieve this focus needs to be entrusted to the value of the object-related behavior and service areas (service areas will also be introduced in the latter part of the article).
To consider the most recent version of the code, we have to divide the behavior of the Itinerary , but a closer look, we added a validation rule in the latter part of the increased demand, then this rule we can transfer to the value object? The answer is, I can. And the transfer is necessary, because the efficacy of the notes should belong to this act is often its own. Like self-efficacy when the machine starts, this behavior is part of the operator or a machine yourself?
So we come to the part of the transfer value object behavior, optimized code might look like this:

public class Itinerary
{
    public int ID { get; set; }

    public List<Person> Participants { get; set; }

    public List<Address> Places { get; set; } 

    public ItineraryNote  Note { get; set; } 

    public ItineraryTime TripTime { get; set; }

    public ItineraryStatus Status { get; set; }

    //ctor

    public void ChangeNote(string content)
    {
        Note  = new ItineraryNote(content);
    }
}

public class ItineraryNote
{
    public string Content { get; set; }
    public DateTime NoteTime { get; set; }

    public ItineraryNote(string content)
    {
        if(content.Length > 200 )
            throw new NoteIsOverlengthException();
        Content = content;
        NoteTime = DateTime.Now;
    }
}

Vision is a beautiful reality is cruel

Here, we really seem to be plain sailing: the establishment of an entity of their own, and some blend of the value of the object, the behavior of the entity is also within the highly gathered in them. It is not that we can directly DDD landed it? Sorry, just as the subtitle, like, reality is really very cruel. If you only read from the code and business processes, we may indeed have been a success, but! ! ! We need to save our data, that is persistent. Because the entity contains a lot of value object, the value of all the object persistence problem faced, it will encounter even more difficult to make double! About the value of the object persistence difficulties can refer to an article on how to use DDD - Value Objects .

We look back at the last edition of the code, we have two sets of attributes (Participants, Places). Persistence single value object it has given us a headache, and now we have to face the persistent problem of the value of a collection of objects. If you by using the EF Core ORM framework to carry out this kind of persistence operations, you will find that we have to add an ID to the value of the object in the List, then the value of the object has a unique identifier has apparently become the entity that It is a very scary thing. We worked so hard to build domain model in the last step landing actually become changed, and this is often an important reason DDD landing difficult, limited by the ORM framework or relational database, resulting in domain model constantly being disrupted, the reconstruction field the model becomes more and more grotesque, eventually wrote back to the traditional three-tier architecture or oriented database modeling.

But at least for now, believe what they had seen, carefully considered and found that the value of projects in the field of objects and entities you have, do not know because of persistent problems and give up and compromise, which is why we should have the courage to developers. In a later article, we will be on a number of issues and the value of the object entity proposing solutions, including of course the persistence of the problem.

to sum up

In this paper we introduce the concept of experience entities and entities related to the entity how to use the actual code, keep in mind the people before us: for example, "entities must be based on the current field of environment (context) of" , "entity within the height of poly and autonomy " , " should focus on the behavior of an entity rather than data, " and so on. Future articles will bring entities and value objects for all content areas as well as some of the considerations services.

Guess you like

Origin www.cnblogs.com/lonelyxmas/p/12065792.html