[JAVA] Aus der Gewohnheit, Wertobjekte für ein objektorientiertes Verständnis zu schaffen

Einführung

Im letzten Jahr konnte ich endlich objektorientierten Code schreiben. Ich habe 1995 zum ersten Mal etwas über Objektorientierung gelernt, also hat es mehr als 20 Jahre gedauert.

Der Grund, warum ich objektorientierten Code schreiben konnte Dies liegt daran, dass ich versucht habe, unter Berücksichtigung des Wertobjekts zu schreiben.

Was ist ein Wertobjekt?

Die einfachste Definition ist die Übersetzung des Artikels von Dr. Martin Fowler (Value Object) [^ 1].

Implementierungsbeispiel in Java

Im Fall von Java ist es gut, die folgenden zwei zu erfüllen. Es ist nicht direkt verwandt, implementiert aber auch toString ().

  1. Implementieren Sie equals () und hashCode ()
  2. Alle Felder sind endgültig [^ 2]

Implementieren wir beispielsweise eine [java.time.Year] [] -ähnliche Klasse, MyYear. Es ist mühsam, equals () und hashCode () richtig zu implementieren, daher überlasse ich es 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 +
                '}';
    }
}

Sie können Apache Commons Lang auch für die Implementierung verwenden. Es verwendet Reflexion, aber die Beschreibung ist einfach. (Einige APIs verwenden keine Reflektion.)

Der Grund, warum SHORT_PREFIX_STYLE für toString () verwendet wird, ist Sie benötigen keinen Hash-Code für das Objekt, sondern nur den Wert des Feldes.

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);
    }
}

verdienen

Derzeit gibt es drei Hauptvorteile.

Einfach zu aggregierende Logik

Wenn Sie beispielsweise eine Methode möchten, die nächstes Jahr zurückgegeben wird, können Sie sie in der MyYear-Methode implementieren. Die Logik ist auf eine Klasse konzentriert, was das Ändern erleichtert.

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

Kann als Kartenschlüssel verwendet werden

Es kann wie folgt als Schlüssel verwendet werden.

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. gleich()Null, wenn es keine gibt
    }
}

Einfach zu schreibende Tests

Es ist in Ordnung, Objekte normal zu vergleichen. Wenn Sie nicht gleich () definieren, müssen Sie einen Getter definieren, um den Wert des Feldes zu erhalten.

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);
    }
}

Warum Wertobjekt

Objektorientierte Definitionen umfassen häufig "Kapselung", "Vererbung" und "Polymorphismus". Abgesehen vom Polymorphismus passen die beiden anderen nicht ganz zusammen.

Encapsulation ist kein Setter / Getter, aber ich konnte nicht herausfinden, was ich schreiben soll, ob Vererbung wirklich notwendig ist und so weiter.

Da ich jedoch angefangen habe, Wertobjekte richtig zu erstellen, zögere ich weniger und kann Code schreiben, der leicht zu verstehen ist. Die einzige Schwäche ist "es ist ein Schmerz, zuerst zu schreiben", aber ich denke, das sind notwendige Kosten.

abschließend

Eigentlich denke ich, dass domänengesteuertes Design leichter zu verstehen ist als objektorientiert, aber ich dachte, dass es zu ausgefallen ist, also habe ich mich vorerst auf Value Object konzentriert.

Wenn Sie es ernsthafter machen wollen (?), Denke ich, dass der folgende Aufsatz, auch "OO Code Training Gibbs" genannt, hilfreich sein wird. Dies ist jedoch ziemlich schwierig. Ich kann nicht ... (ヽ ´ω`)

[^ 1]: Es wurden verschiedene Ergänzungen zum Originaltext vorgenommen (ValueObject), aber diesmal handelt es sich nur um eine Definition, daher werde ich die alte Beschreibung verwenden. [^ 2]: Selbst wenn final hinzugefügt wird, kann nicht gesagt werden, dass es unveränderlich ist, wenn List usw. enthalten ist, aber die Erklärung wird hier weggelassen. [java.time.Year]: https://docs.oracle.com/javase/jp/8/docs/api/java/time/Year.html

Recommended Posts

Aus der Gewohnheit, Wertobjekte für ein objektorientiertes Verständnis zu schaffen
Extrahieren Sie ein bestimmtes Element aus der Liste der Objekte
Wiedereinführung in Java for Humanities 0: Den Akt der Programmierung verstehen
Ein grundlegendes Verständnis des Flusses der rekursiven Verarbeitung anstreben
Die Geschichte des Wechsels von Amazon RDS für MySQL zu Amazon Aurora Serverless
[Herausforderung CircleCI von 0] Lernen Sie die Grundlagen von CircleCI
Samshin über den Wert des versteckten Feldes
Die Geschichte von RxJava, das unter NoSuchElementException leidet
WebMvcConfigurer-Memorandum von Spring Boot 2.0 (Spring 5)
Messen Sie einfach die Größe von Java-Objekten
Vertiefte mein Verständnis der Zusammenführungsmethode
Finden Sie den Unterschied von einem Vielfachen von 10