Аннотации в доменных объектах с JPA нарушают базу данных — это деталь

Что вы думаете о разделении моделей постоянства и моделей предметной области? Я читал, что вам не нужно смешивать проблемы сохранения с вашими бизнес-задачами (DDD, чистая архитектура, Мартин Фаулер, Эрик Эванс и многое-многое другое). Тем не менее, я все еще вижу во всех проектах модели предметной области, аннотированные непосредственно такими аннотациями ORM, будучи моделью предметной области, связанной с механизмом персистентности, достигающей анемичной модели и нарушающей другие принципы.

//PersistenceJPA entity
@Entity
@Table(name="training_cycle")
class TrainingCycle {
    @Id
    private Long id;
    private String name;

    @Column(name="discipline_id")
    @JoinColumn(name="discipline_id")
    private Long disciplineId; //Referencing by Id because Discipline is another Aggregate ROOT

    //EmptyConstructor, getters and setters avoided
}

//PersistenceJPA entity
@Entity
@Table(name="training_cycle")
class Discipline {
    @Id
    private Long disciplineId;
    private String name;
    //EmptyConstructor, getters and setters avoided
} 

Поэтому, если вы хотите следовать чистым принципам, вам нужно разделить модель домена и модель постоянства (как показано ниже), чтобы иметь модель домена с бизнес-поведением (это позволяет избежать анемичной модели и следует SRP), и поэтому вам необходимо сопоставить модель домена с модель постоянства (с типичными методами, такими как mapToEntity(DomainModel DM) и mapToDomain(PersistenceModel PM), возможно, в преобразователе/преобразователе, возможно, в классе репозитория), когда вы хотите взаимодействовать с Datastore и наоборот, когда вы хотите получить данные из базы данных.

class Discipline {
    private DisciplineId disciplineId;
    private String name;

    public Discipline(DisciplineId disciplineId, String name) {
        this.disciplineId = disciplineId;
        this.name = name
    }
}

public class TrainingCycle{
    private TrainingCycleId trainingCycleId;
    private String name;
    private DisciplineId disciplineId;

    public TrainingCycle(TrainingCyleId trainingCycleId, String name, DisciplineId disciplineId) {
        this.trainingCycleId = trainingCycleId;
        this.name = name;
        assignDiscipline(disciplineId);
    }

    public void assignDiscipline(DisciplineId aDisicplineId) {
        if(aDisicplineId == null) {
            throw new IllegalArgumenException("Discipline cannot be null")
        }
        this.disciplineId = aDisicplineId;
    }
}


@Entity
@Table(name="training_cycle")
class TrainingCycleJpa {
    @Id
    private Long id;
    private String name;

    @Column(name="discipline_id")
    @JoinColumn(name="discipline_id")
    private Long disciplineId; //Referencing by Id because Discipline is another Aggregate ROOT

    //EmptyConstructor, getters and setters avoided
}


@Entity
@Table(name="training_cycle")
class DisciplineJpa {

    @Id
    private Long disciplineId;
    private String name;
   //EmptyConstructor, getters and setters avoided
}

class TrainingCyleJpaRepository implements TrainigCycleRepository {

    public void create(TrainingCycle trainingCycle) {
        entityManager.persist(this.mapToEntity(trainingCycle)
    }

    public TrainingCycle create(TrainingCycleId trainingCycleId) {
        return this.mapToDomain(entityManager.find(TrainingCycleId));
    }
}

Итак, обсуждение/вопрос заключается в том, чтобы разделить или не разделить модель персистентности из модели домена? Когда разделять, а когда нет? В большинстве проектов, не говоря уже о тех, которые я видел в качестве примера, я видел, как они объединяют аннотации модели постоянства в модели предметной области, в то время как гуру всегда торгуют DataStore — это деталь.

Большое спасибо.


person Developer    schedule 13.08.2020    source источник


Ответы (2)


Пожалуйста, ознакомьтесь с этим очень похожим вопросом: Являются ли постоянные аннотации в объектах домена плохой практикой?

Я думаю, что как инженеры мы должны быть прагматичными. Любые лучшие практики, принципы или предложения гуру должны помочь. Они не должны делать хуже. Поэтому я предлагаю относиться к ним как к руководству, а не как к строгим правилам. Например, я в целом согласен с тем, что база данных — это деталь. Но мы редко меняем эту деталь.

С другой стороны, аннотации не выполняют никакого кода. И сцепление не так уж и плохо. Ваш объект домена может одновременно быть объектом JPA, и он будет очень чистым и полезным. Кстати, это не нарушает принцип единой ответственности (SPR). Если вы думаете, что это так, ознакомьтесь с ПРЕКРАСНЫМ объяснением автора дяди Боба.

person Taras Boychuk    schedule 13.08.2020
comment
annotations do not execute any code, но есть код, который ищет аннотации и выполняет другой код. Таким образом, аннотации эффективно выполняют код. - person René Link; 26.08.2020

Да, эти аннотации являются деталями, и их следует держать подальше от сущностей чистой архитектуры.

Не путайте объект имени в чистой архитектуре и аннотацию @Entity из вашей структуры постоянства. Это разные вещи.

Есть видео дяди Боба о чистой архитектуре, и в конце он делает это действительно ясно, потому что он говорит:

сущности не являются экземплярами таблиц базы данных. Обычно это конструкции из множества таблиц базы данных.

В другом видео он рассказывает о внедрении зависимостей и аннотации, которые используют эти фреймворки. Что ж, внедрение зависимостей не имеет ничего общего с постоянством, о котором вы просили, но это видео ясно показывает, что дядя Боб думает об аннотациях фреймворка в сценарии использования или на уровне сущностей чистой архитектуры.

А в этом видео он ясно дает понять, что сущности не должны иметь сведений о сохранении. Неважно, спящий это или JPA.

person René Link    schedule 26.08.2020