[JAVA] Notes personnelles DDD

introduction

Sentiments divers sur le chemin

――Lorsque vous lisez l'explication du modèle de domaine et du service de domaine, je suis convaincu que la connaissance des règles métier conduira à l'isolement des problèmes.

Hmmm, je pense que l'application Todo a un mauvais exemple. Dans le cas de Todo, il n'y a pas d'autre choix que de le saisir ou de le supprimer, et il n'y a presque aucun calcul. Le seul calcul qu'un objet de collection devrait avoir est de trier la date d'échéance dans l'ordre croissant, de collecter les favoris (vrai) et de les aligner à l'avant et le reste à l'arrière. Vous pouvez calculer la digestibilité de Task. Il n'y a aucune responsabilité de calculer quelque chose avec un Todo.

layer

+-- domain
|    |
|    +-- model
|    |    |
|    |    +-- Entity -- Aggregate
|    |    |
|    |    `-- Value Object
|    |
|    +-- Factory
|    |
|    +-- Repository ( command , query )
|    |
|    +-- Service
|    |
|    `-- ( shared )
|
+-- infrastructure - service
|    |                |
|    |                `-- ( mail sender )
|    |
|    `-- ( Repository Implementation )
|         |
|         +-- ( db I/O )
|         |
|         +-- ( file I/O )
|         |
|         `-- ( cache I/O )
|
+-- application -- Service
|
`-- interfaces
     |
     +-- ( controller )
     |    |
     |    `-- ( REST )
     |          |
     |          +-- ( XML )
     |          |
     |          `-- ( JSON )
     |
     +-- ( view )
     |    |
     |    `-- ( HTML )
     |
     `-- ( socket )


domain model

Livres de référence:

--Concept / Explication

Entity

Présentation de l'entité



//Attributs variables autres que les identifiants
//Parce que les attributs sont indépendants les uns des autres dans cette classe@Setter est spécifié
//Lorsque les attributs sont liés les uns aux autres, effectuez des opérations d'attribut via cette classe de logique métier.
@Getter
@Setter
public final class Todo extends AbstractEntity<Todo> implements ValueObject {

    // (AbstractEntity::private final UUID identifier)
    private Title title;
    private DueDate dueDate;
    private TaskList taskList;
    private Memo memo;
    private Favorite favorite;

    public Todo(final EntityIdentifier<Todo> identifier, final Title title, final DueDate dueDate, final TaskList taskList, final Memo memo, final Favorite favorite) {
        super(identifier);
        Validate.notNull(title);
        Validate.notNull(dueDate);
        Validate.notNull(taskList);
        Validate.notNull(memo);
        Validate.notNull(favorite);

        this.title = title;
        this.dueDate = dueDate;
        this.taskList = taskList;
        this.memo = memo;
        this.favorite = favorite;
    }

    @Override
    public Todo clone() {
        return super.clone();
    }

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

    @Override
    public int hashCode() {
        int result = Objects.hashCode(entityIdentifier);
        result = 31 * result;
        return result;
    }
}

Value Object

Présentation de ValueObject



// ----Fondamentalement, cela--------------------------

//Les attributs sont immuables
@Getter
public final class Task implements ValueObject {
    private final String value;
    private final Boolean done;

    public Task(final String value) {
        Validate.notNull(value);

        this.value = value;
        this.done = false;
    }

    public Task(final String value, final Boolean done) {
        Validate.notNull(value);
        Validate.notNull(done);

        this.value = value;
        this.done = done;
    }

    @Override
    public boolean equals(final Object that) {
        if (this == that) {
            return true;
        }
        if (that == null || getClass() != that.getClass()) {
            return false;
        }
        Task o = (Task) that;
        if (!value.equals(o.value)) {
            return false;
        }
        if (!done.equals(o.done)) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int result = Objects.hashCode(value);
        result = 31 * result + Objects.hashCode(done);
        return result;
    }
}



// ----Avoir un objet de valeur dans l'enfant--------------------------

//Les attributs sont immuables
//Cependant, si l'attribut est un objet tel que List, une certaine ingéniosité est requise.
public final class TaskList implements ValueObjectList<TaskList, Task> {
    private final List<Task> taskList;

    public TaskList() {
        taskList = Collections.unmodifiableList(new ArrayList<>());
    }

    public TaskList(final List<Task> list) {
        Validate.notNull(list);

        // unmodifiableList()La raison est
        //Liste retournée en passant par référence<Task>Assurez-vous que le contenu ne peut pas être réécrit
        //Si vous souhaitez le réécrire, vous souhaitez forcer l'utilisation du constructeur.
        //Puisque la déclaration finale ne fonctionne pas même dans l'élément, elle est utilisée dans cette position même au sens déclaratif.
        taskList = Collections.unmodifiableList(list);
    }

/*
  Collections.unmodifiableList()La raison de l'utilisation
Si vous ne l'utilisez pas, le code de test suivant ne passera pas et vous ne pouvez pas garantir que les attributs ne changeront pas.

Si vous utilisez taskList.set(0, after)UnsupportedOperationException se produit dans
Si vous souhaitez réécrire l'élément, ArrayList<>(taskList)En passant au constructeur de TaskList
Lors de la réécriture des éléments, les attributs peuvent être garantis immuables (= un autre objet avec des attributs différents car le constructeur est utilisé).

        TaskList target = new TaskList();

        Task before = new Task("Acheter du lait", false);
        target.add(before);
        assertEquals(1, target.getList().size());

        //Écraser le premier de la liste récupérée par un autre objet
        List<Task> taskList = target.getList();
        Task after = new Task("Vendre du lait", true);
        taskList.set(0, after);

        //Le montant écrasé n'est pas reflété dans la variable avant d'être sécurisé avant l'écrasement.
       assertEquals(before.getFavorite(), target.getList().get(0).getFavorite());
 */

    private static void accept(final Task w) {
    }

    public Optional<Task> find(final Task searchTask) {
        Validate.notNull(searchTask);

        Optional<Task> ret = Optional.empty();

        for (Task existTask : getList()) {
            if (existTask.equals(searchTask)) {
                ret = Optional.of(existTask);
                break;
            }
        }

        return ret;
    }

    public List<Task> getList() {
        return taskList;
    }

    public TaskList add(final Task... t) {
        Arrays.stream(t).forEach(Validate::notNull);

        List<Task> result = new ArrayList<>(taskList);
        Arrays.stream(t).forEach(
                v -> find(v).ifPresentOrElse(
                        TaskList::accept,
                        () -> result.add(v)
                )
        );

        return new TaskList(result);
    }

/*
La raison de ma régénération et de mon retour est
L'attribut interne est Collections#unmodifiableList()Il ne peut pas être modifié car il n'a pas changé.

En guise de mise en garde, List#add(Object):Si vous l'utilisez comme booléen, cela ne sera pas mis à jour et vous ne recevrez aucune nouvelle valeur.
*/

    public TaskList remove(final Task... t) {
        Arrays.stream(t).forEach(Validate::notNull);

        List<Task> result = new ArrayList<>(taskList);
        Arrays.stream(t).forEach(
                v -> find(v).ifPresent(result::remove)
        );

        return new TaskList(result);
    }

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

    @Override
    public int hashCode() {
        int result = Objects.hashCode(taskList);
        result = 31 * result;
        return result;
    }
}

factory

Aperçu de l'usine


public class TodoFactory implements EntityFactory<Todo> {

    @Override
    public Todo create() {
        return create("");
    }

    @Override
    public Todo create(final EntityIdentifier<Todo> identifier) {
        Validate.notNull(identifier);

        Title t = new Title("");
        DueDate d = new DueDate();
        TaskList l = new TaskList();
        Memo m = new Memo();
        Favorite f = new Favorite();

        return new Todo(identifier, t, d, l, m, f);
    }

    /**
     * {@link Title}Spécifier{@link Todo}créer
     *
     * @param title
     * @return
     */
    public Todo create(final String title) {
        Validate.notNull(title);

        EntityIdentifier<Todo> identifier = new DefaultEntityIdentifier<>(Todo.class, UUID.randomUUID());
        Title t = new Title(title);
        DueDate d = new DueDate();
        TaskList l = new TaskList();
        Memo m = new Memo();
        Favorite f = new Favorite();

        return new Todo(identifier, t, d, l, m, f);
    }
}

repository

agrégation

domain service

  1. L'opération implique le concept de domaine, qui n'est pas une ** partie naturelle d'une entité ou d'un objet de valeur **.
  2. L'interface est définie du point de vue des ** autres éléments du modèle de domaine **.
  3. Il n'y a aucun état ** dans l'opération **.

application service

infrastructure service

interfaces

--GET / POST / PUT / DELETE et autres endroits pour recevoir

Recommended Posts

Notes personnelles DDD
jouer des notes personnelles de cadre
apache POI mémo personnel crossfish21
Notes personnelles de First Play Framework
Trier dans la liste, pour mémo personnel
JUnit 4 notes
note java
notes synchronisées
Validation des rails et null: fausses notes personnelles