Value object in 3 minutes

Assumed reader

--Business application engineer who has troubles in class design --Those who want to get an overview of Value Objects

Common classes and their problems

Common class

Let's create a class using an object-oriented language such as Java or Python. In the example below, the task is represented as a class, with the task name, points, and deadline held as fields. This is a common class that uses String type and int type.

Task.java


String taskName;
int point;
Date dueDate;
...

It is also a common implementation pattern to hold getter / setter methods for each field you hold.

Task.java


    public Point getPoint() {
        return point;
    }
    public void setPoint(Point point) {
        this.point = point;
    }
    ...

A brief summary of the characteristics of "common" classes.

--Fields are declared using language-provided types such as int and Date. --getter / setter method is implemented

What's wrong with such a general class?

Common class problems

I mentioned two features earlier, but common classes have major problems related to them. That is, despite being a class that exists to create business applications, ** "it has a structure that allows values and operations that violate business rules" **. Let's take a look at the actual source code.

Problems to see in the code

As an example, consider a field called point in the previous class. Let's assume that there is a business rule that "points should be from 0 to 1000". However, since the point in the Task class is declared as an int type, you can also do this.

task.setPoint(-2000);

A point that violates the business rule of -2000 is set. Making this possible makes it easier for you to create bugs in your business logic. Furthermore, ** it is a logical bug from the viewpoint of business rules, and since no error occurs as a program, it becomes difficult to find **, which is a big problem.

Of course, since int type and Date type do not know the business rules of individual applications, it is not possible to prevent acts that violate the business rules. Furthermore, by allowing the setter method, any value can be set freely from the outside.

How to solve the problem-Try using value objects-

To explain a value object in my own interpretation, it is ** "a class that expresses the rules of units and values used in business" **.

Value object to look at in code

If you look at the actual code, you can see it somehow. The points are the following two points.

-** Define business rules ** (clearly declare constraints such as MIN, MAX) -** Do not allow operations that violate business rules ** (Throw an exception if violated)

Originally, it was a setter for int type and "anything can be set", but the setter that ignores the business rules is not used. Or rather, don't make it. In the value object, you need to create a method that sets the value based on the business rule.

For example, when the add method is called, canAdd is called next and it is checked whether a value (a value other than 0 to 10000) that violates the business rule is passed. If there is no problem, a new instance of Point will be created as it is, and if there is a problem, an exception will be thrown so that a value that violates the business rules is not set.

Point.java


public class Point {

    static final int MIN = 0;
    static final int MAX = 10000;

    int value;

    public Point(int value) {
        if (value < MIN) throw new
                IllegalArgumentException("Injustice:" + MIN + "Less than");
        if (value > MAX) throw new
                IllegalArgumentException("Injustice:" + MAX + "over-");
        this.value = value;
    }

    Point add(Point other) {
        if (!canAdd(other)) throw new
                IllegalArgumentException("Illegal: the total is" + MAX + "that's all");
        int added = addValue(other);
        return new Point(added);
    }

    boolean canAdd(Point other) {
        int added = addValue(other);
        return added <= MAX;
    }

    private int addValue(Point other) {
        return this.value + other.value;
    }
}

The created value object Point is declared and used in the original Task class.

Task.java


//Only points are changed to value objects
String taskName;
Point point;    //Originally[int point;]
Date dueDate;

Also, unlike the "common" classes mentioned earlier, you can easily get an overview of business rules just by looking at the value objects. In this way, value objects are a very convenient design method that not only prevents bugs from being introduced but also helps to understand specifications by expressing business rules as classes **. Please use it next time.

Notes

This article describes the "value objects" that appear in Domain Driven Design, but it doesn't touch on all the strict definitions and characteristics of value objects, it's just an overview. Please note.

References

Principles of system design useful in the field ~ Object-oriented practical techniques that make changes easy and safe

Recommended Posts

Value object in 3 minutes
Points when mapping Value Object in MyBatis
G1 Garbage Collection in 3 Minutes
Java Stream API in 5 minutes
Mapping to a class with a value object in How to MyBatis
Eliminate Rails FatModel with value object
Continuous inspection in 5 minutes with SonarQube
Initial value when there is no form object property in Spring request
Android development, how to check null in the value of JSON object
Object registered in session must be Serializable
Reverse Key from Value in Java Map
"Hello, World!" With Kotlin + CLI in 5 minutes
Immutable (immutable) List object conversion function in Java8
Return custom object with @Query in spring-data-jpa
Understand in 5 minutes !! How to use Docker