[JAVA] De l'habitude de créer des objets de valeur pour une compréhension orientée objet

introduction

Au cours de la dernière année, j'ai enfin pu écrire du code orienté objet. J'ai appris l'orientation objet pour la première fois en 1995, donc cela a pris plus de 20 ans.

La raison pour laquelle je suis devenu capable d'écrire du code orienté objet C'est parce que j'ai essayé d'écrire avec l'objet de valeur à l'esprit.

Qu'est-ce qu'un objet de valeur?

La définition la plus simple est la traduction de l'article écrit par le Dr. Martin Fowler (Value Object) [^ 1].

Exemple d'implémentation en Java

Dans le cas de Java, il est bon de satisfaire les deux suivants. Ce n'est pas directement lié, mais il implémente également toString ().

  1. Implémentez equals () et hashCode ()
  2. Tous les champs sont définitifs [^ 2]

Par exemple, implémentons une classe semblable à [java.time.Year] [], MyYear. Il est difficile d'implémenter correctement equals () et hashCode (), donc je laisse cela à IDE (IntelliJ IDEA).

public final class MyYear {
    private final int year;

    private MyYear(int year) {
        this.year = year;
    }

    public static MyYear of(int year) {
        return new MyYear(year);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        MyYear myYear = (MyYear) o;

        return year == myYear.year;
    }

    @Override
    public int hashCode() {
        return year;
    }

    @Override
    public String toString() {
        return "MyYear{" +
                "year=" + year +
                '}';
    }
}

Vous pouvez également utiliser Apache Commons Lang pour l'implémentation. Il utilise la réflexion, mais la description est simple. (Certaines API n'utilisent pas de réflexion)

La raison pour laquelle SHORT_PREFIX_STYLE est utilisé pour toString () est Vous n'avez pas besoin du code de hachage pour l'objet, vous n'avez besoin que de la valeur du champ.

import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

public final class MyYear {
    private final int year;

    private MyYear(int year) {
        this.year = year;
    }

    public static MyYear of(int year) {
        return new MyYear(year);
    }

    @Override
    public boolean equals(Object o) {
        return EqualsBuilder.reflectionEquals(this, o);
    }

    @Override
    public int hashCode() {
        return HashCodeBuilder.reflectionHashCode(this);
    }

    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
    }
}

mérite

Pour le moment, il y a trois avantages majeurs.

Logique facile à agréger

Par exemple, si vous voulez une méthode qui renvoie l'année prochaine, vous pouvez l'implémenter dans la méthode MyYear. La logique est concentrée dans une classe, ce qui facilite le changement.

public MyYear nextYear() {
    return new MyYear(this.year + 1);
}

Peut être utilisé comme clé de carte

Il peut être utilisé comme clé comme suit.

import java.util.HashMap;

public final class Main {
    public static void main(String[] args) {
        var myMap = new HashMap<>();
        myMap.put(MyYear.of(2018), "2018");
        System.out.println(myMap.get(MyYear.of(2018))); // =>2018. équivaut à()Null s'il n'y a pas
    }
}

Des tests faciles à rédiger

Il est normal de comparer des objets. Si vous ne définissez pas equals (), vous devrez définir un getter pour obtenir les valeurs des champs.

import org.junit.Test;

import static org.assertj.core.api.Assertions.assertThat;

public final class MyYearTest {
    @Test
    public void testMyYearNext() {
        MyYear now = MyYear.of(2018);
        MyYear next = MyYear.of(2019);

        assertThat(now.nextYear()).isEqualTo(next);
    }
}

Pourquoi Value Object

Les définitions orientées objet incluent souvent «encapsulation», «héritage» et «polymorphisme». Mis à part le polymorphisme, les deux autres ne correspondent pas tout à fait.

L'encapsulation n'est pas un setter / getter, mais je n'ai pas été en mesure de trier ce qu'il faut écrire et si l'héritage est vraiment nécessaire.

Cependant, depuis que j'ai commencé à créer correctement des objets de valeur, j'ai moins d'hésitation et je peux écrire du code facile à comprendre. La seule faiblesse est "c'est pénible d'écrire au début", mais je pense que c'est un coût nécessaire.

en conclusion

En fait, je pense que la conception axée sur le domaine est peut-être plus facile à comprendre que la conception orientée objet, mais je pensais que c'était trop bizarre, alors je me suis concentré sur Value Object pour le moment.

Si vous voulez le faire plus sérieusement (?), Je pense que l'essai suivant, également appelé "OO Code Training Gibbs", vous sera utile. Cependant, c'est assez difficile. Je ne peux pas ... (ヽ ´ω`)

[^ 1]: Divers ajouts ont été faits au texte original (ValueObject), mais cette fois ce n'est qu'une définition, donc j'utiliserai l'ancienne description. [^ 2]: Même si final est ajouté, on ne peut pas dire qu'il est invariant si List etc. est inclus, mais l'explication est omise ici. [java.time.Year]: https://docs.oracle.com/javase/jp/8/docs/api/java/time/Year.html

Recommended Posts

De l'habitude de créer des objets de valeur pour une compréhension orientée objet
Extraire un élément spécifique de la liste des objets
Réintroduction à Java for Humanities 0: Comprendre l'acte de programmation
Viser une compréhension de base du flux de traitement récursif
L'histoire du passage d'Amazon RDS pour MySQL à Amazon Aurora Serverless
[Challenge CircleCI from 0] Apprenez les bases de CircleCI
Samshin sur la valeur du champ caché
L'histoire de RxJava souffrant de NoSuchElementException
Mémorandum WebMvcConfigurer de Spring Boot 2.0 (printemps 5)
Mesurez facilement la taille des objets Java
J'ai approfondi ma compréhension de la méthode de fusion
Trouvez la différence à partir d'un multiple de 10