Information entity object

In the design of object model, there is a common business is the design of information entity class. If you don’t talk about the general business of “information entity objects,” you’re going to vacillate between data and object models, and end up walking away from domain-driven design as you constantly try.

Entity Object

From the point of view of philosophical concept, the object that exists objectively and can be distinguished from each other is substance. It simply means that everything in the world is solid. In software design, entities make more concrete applications.

In an entity-relationship diagram, for example, an entity is an abstraction of a class of things. Different entities are distinguished by their entity types, typically represented by entity names: users, roles, tables, benches, rooms, and so on. If only understood as the entity name is not rigorous, because it is the whole entity type name, so the abstraction of the object is the abstraction of a class of things, rather than the abstraction of the noun.

Entity classes are conceptually data-intensive classes – their primary purpose is to store data and provide access to that data. In many cases, entity classes are persistent, which means that data is persistent and needs to be stored in a file or database.

Another thing that this paragraph emphasizes is that entities need to be persistent.

Information entity object

The focus of today’s discussion is information entity objects. In the past, when people talked about domain models, basically the hallmark of domain models was congestion. This kind of thinking makes it difficult and painful for the information entity model to survive in your design. In order for information entity objects to be well received by you, the object concept is emphasized again: the domain model is based on the object model, which consists of properties and methods.

The information entity object is basically a form data object. The basic characteristic of this kind of entity is that there are many attributes and almost no methods. Common operations are CRUD and data validation. The diagram below:

Seeing this, it feels like form data is no longer a domain model or “solution to software core complexity” as it is often said. In fact, this kind of thinking is a misunderstanding of domain modeling and object modeling. To solve this misunderstanding, start modeling the object of form data.

The Form object

Form means Form or Form. For example, when people are asked to fill out a census form, they are actually filling out a form. In JS, a Form is an object that contains the commit and reset operations. $(“#form”).submit() and $(“#form”).reset().

The form data

When we look at the form page, we should have a basic understanding that the form object is a wrapper around the form data, and the form data is usually an entity object, so we can see that the form view is actually editing the entity object. Now we can design a domain model from the form above:

class Project {
    #id: string
    #title: string
    #startDate: Date
    #endDate: Date
    #goal: string
    #standard: string
    #clients: string[]
    #invites: string[]
    #weight: number
    #scope: number
}
Copy the code

As far as the Project model is concerned, it does not have any operation method. It is not rigorous to call such a model without operation method anemia model directly.

Supplement:

I’ve always thought that when you talk about the anemia model, you should talk about anemia due to the symptoms of blood loss. Blood loss is simply expressed as the loss of blood that belongs to a person, from the body. Not when you see a pot of pig’s blood, you feel like you’re losing it, and then you have to pour it on yourself.

For a long time, people’s understanding of the anemia model is not rigorous enough. Generally speaking, people think that the model with only attributes and little or no business logic is the anemia model and is not rigorous. An important indicator to identify an anaemic model is whether the business logic that the model itself needs to handle leaks.

If the model itself has no business logic to deal with, but only attributes, it should not be called an anaemic model.

If the model itself needs to process the business logic but does not process it, the caller processes the business logic that belongs to the model itself.

Data validation

Consider the question, is data validation of domain objects something that domain objects themselves do?

When I was filling out the census form, the officer in charge of the census told me what I needed to fill out. After I filled it out, I checked it carefully and found no problems to submit to the staff. The staff carefully checked and told me that there were several fields that were not filled in, and THEN I immediately filled in these fields. Finally she checked again and found nothing wrong and handed it to her.

Validation of Form data is often handled externally, such as the Validation-API framework provided in Java development, and the Form component provided in most front-end UI component libraries, which also wraps validation externally rather than providing validation on the data itself.

Operation method

At present, the Project model does not need operation methods, and the verification is not done by the Project itself, so will it include operation methods?

If at this point the Project object satisfies the business requirements, no action methods are really required. But as you learn more about the domain, the model changes. For example, we would add a creation time field to the Project object as follows:

class Project {
    // ...
    #createdTime: Date
}
Copy the code

At this time, the assignment of createdTime field is involved, and the whole model may become an anaemic model if it is careless.

In judging the true age of a person, the medical examiner can accurately infer the age of the individual through the bone development shown on the X-ray films of the six major joints of the living body, including shoulder, elbow, wrist, hip, knee and ankle, and control the error between the bone age and the actual age within the range of ±1 year.

This paragraph is very important for understanding the assignment of the createdTime field.

Consider a question: in reality, is the bone age of a human set externally, or is it set internally during initialization?

External Settings:

class Person {
    #createdTime: Date

    public get createdTime() {
        return this.#createdTime
    }
    
    public set createdTime(createdTime: Date) {
        this.#createdTime = createdTime
    }
}
Copy the code

Internal Settings:

class Person {
    #createdTime: Date

    public constructor() {
        this.#createdTime = new Date()}public get createdTime() {
        return this.#createdTime
    }
}
Copy the code

Have you ever seen a man who, when he was born, could just get a new set of bones in his whole body? So createdTime is assigned at the first initialization and is assigned internally.

For entity objects that need to be persisted, the ORM framework requires the object to provide a no-parameter constructor, because the ORM framework needs to instantiate the object through the no-parameter constructor every time. Then operations like this.#createdTime = new Date() within the constructor method will assign repeatedly. Things that need to be done for the first time in the life cycle of an entity object are typically placed in a custom business-meaningful method. As follows:

class Person {
    #createdTime: Date

    public get createdTime() {
        return this.#createdTime
    }

    public create() {
        if (this.#createdTime ! = =undefined) {
            throw new Error("Initialized")}this.#createdTime = new Date()}}Copy the code

Back to the complete Project object model:

class Project {
    #id: string
    #title: string
    #startDate: Date
    #endDate: Date
    #goal: string
    #standard: string
    #clients: string[]
    #invites: string[]
    #weight: number
    #scope: number
    #createdTime: Date
    // getters & setters ...
    public create() {
        // ...
        this.#createdTime = new Date()}}Copy the code

The information entity object is a CRUD for common business, such as articles, user information, store information, customer information, account information, various forms and other information objects.

It is very painful for a friend who has been trying to pursue the hyperemic model that everything needs to be designed with rich behaviors, but also needs to design a behavior for him that the model does not have.

Don’t assume that everything in the domain model needs action methods, such as:

class Project {
    #title: string
    #goal: string
    // ...
    public update(request : ProjectRequest) {
        this.#title = request.title
        this.#goal = request.goal
        // ...}}Copy the code

Objects are designed to be made up of properties and methods, so when you think about models you should also think about properties and methods together. There is a misunderstanding in understanding properties, that is, the difference between field and property, which will be discussed separately later.

conclusion

In many cases, the domain model or object model should be thought of as updating data through behavioral manipulation methods, with properties providing only read operations. However, for entity objects that focus on information, there are more CURD operations.

The anemia model is explained in more detail through supplementary explanation, hoping to feel the situation of blood loss from oneself, so as to realize the necessity of entity object to its own business encapsulation.

This is followed by a story about filling out a census form to illustrate whether validation of form data is a function of the entity itself. Finally, the create method is designed for the first initialization of the Project entity model.

Add: initiative and passivity have certain influence on object-oriented modeling design, need to think about this problem.