Избегайте использования слоя постоянства на модели для совокупных дочерних элементов - PullRequest
0 голосов
/ 09 февраля 2020

Проблема

Предположим, что следующая модель DDD.

class Building {
    Room[] rooms

    addRoom(String name)  {
        room = new Room(name) // Model
        db.create(room)       // Persistence!!!
        rooms.add(room)       // Model
    }
}

class Room {
    String name
}

Мы можем видеть, что Building является AR и отвечает за создание его агрегата. Room. Моя проблема, когда я пытаюсь Создать Room в базе данных, следуя модели CRUD . В какой-то момент можно создать комнату, поэтому моя модель назовет Building, и она создаст Room. Однако моя модель не должна использовать постоянный слой.

Обратите внимание, , что вы можете добавлять комнаты, что означает, что вы можете иметь Building в базе данных, несовместимой с реальной моделью. Поэтому мне бы пришлось обновить мой Building тоже.

Если я переместлю Создание из Room для базы данных за пределы модели, тогда, когда я обновление my Building в базе данных, Room должно уже существовать в базе данных. Но Room является совокупным дочерним элементом Building, и к нему не должны обращаться другие классы, кроме Building.

Вопрос

Как мне Создать Room в базе данных вне модели, сохраняющей Room как совокупный дочерний элемент?

Ответы [ 2 ]

1 голос
/ 20 февраля 2020

В вашем сценарии, если я не понял неправильно, Building - это агрегат root, который содержит коллекцию Room сущностей (запомните этот агрегат сама тоже является сущностью).

хранилище , которое выглядит примерно так, как должно, должно отвечать за операции персистентности (например, создание, поиск, обновление и т. д. c.) вашего агрегата. root, то есть Building.

public interface Repositoy<Building> {

    Building findById(String buildingId);

    void store(Building building);
}

Вы правильно указали, что операции с доменом (например, добавление места в вашем случае) должны выполняться через совокупность root. Однако совокупный root (или любой другой объект) не должен принимать на себя обязанности по сохранению (как вы сказали: db.create(room)).

Клиент взаимодействует с доменом через служба домена или служба приложений . Они, в свою очередь, извлекают агрегат root через свой репозиторий, вносят необходимые изменения и сохраняют весь агрегат в одной транзакции. Следовательно, при каждой успешной транзакции у вас всегда есть непротиворечивый агрегат с его дочерними элементами в базе данных, и вам не о чем беспокоиться из-за отсутствия родителя, дочернего элемента и т. Д. c.

public class SomeDomainOrApplicationService {

    private Repositoy<Building> repository;

    public void createRoomServiceMethod(String buildingId) {

        // retrieve aggregate root
        Building building = repository.findById(buildingId);

        // modify aggregate
        String roomName; // assign room name
        building.addRoom(roomName);

        // store aggregate
        repository.store(building);
    }
}
.
1 голос
/ 10 февраля 2020

пожалуйста, посмотрите шаблон репозитория, если вы используете DDD - должно стать очевидным, как может работать взаимодействие постоянства и БД.

Проще говоря, репозиторий отвечает за извлечение и хранение агрегатов в целом.

, в вашем случае у вас будет некоторый CrudRepository<Building>, который взаимодействует с БД и хранит здание, каскадируя все комнаты.

Здесь нужно отметить одну вещь: простой композиции между двумя типами объектов может быть недостаточно, чтобы требовать моделирования как совокупности. Если инварианты не существуют и согласованность транзакций не требуется, они также могут быть двумя разными агрегатами, ссылающимися друг на друга (через идентификаторы)

...