Методы добавления и создания репозитория - PullRequest
2 голосов
/ 25 марта 2019

Почему метод репозитория .Add обычно реализуется как принятие экземпляра сущности для добавления, с .Id уже «установленным» (хотя его можно установить заново с помощью отражения), что должно быть обязанностью репо?
Не лучше ли реализовать его как .AddAndCreate?

Например, с учетом сущности Person:

public class Person
{
    public Person(uint id, string name)
    {
        this.Id = id;
        this.Name = name;
    }

    public uint Id { get; }
    public string Name { get; }
}

, почему хранилища обычно реализуются как:

public interface IRpository<T>
{
    Task<T> AddAsync(T entity);
}

а не как:

public interface IPersonsRpository
{
    Task<Person> AddAndCreateAsync(string name);
}

Ответы [ 3 ]

3 голосов
/ 25 марта 2019

почему репозитории обычно реализованы как ...?

Несколько причин.

Исторически, domain-driven-design находится под сильным влиянием книги Эрика Эванса, которая ввела этот термин. Там Эванс предложил, чтобы репозитории обеспечивали семантику коллекции, обеспечивая «иллюзию коллекции в памяти».

Добавление String или даже Name к коллекции Person не имеет особого смысла.

В более широком смысле, выяснение того, как воссоздать сущность из набора параметров, является отдельной обязанностью от хранилища, поэтому, возможно, нет смысла переходить туда (примечание: хранилище часто заканчивается обязанностью восстановления сущность из некоторого сохраненного памятного материала, так что она не является полностью чужой, но обычно есть дополнительная абстракция, «Фабрика», которая действительно выполняет свою работу.)

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

public interface IPersonRepository : IRepository<Person> {
    // Person specific queries go here
}

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

1 голос
/ 22 апреля 2019

Использование Определение Мартина Фаулера:

Репозиторий является посредником между доменом и слоями отображения данных, действуя как коллекция объектов домена в памяти.Объекты клиента создают декларативные спецификации запросов и отправляют их в хранилище для удовлетворения.Объекты могут добавляться и удаляться из репозитория, как и из простой коллекции объектов, и код отображения, инкапсулированный репозиторием, будет выполнять соответствующие операции за кулисами.Концептуально, репозиторий инкапсулирует набор объектов, сохраненных в хранилище данных, и операции, выполняемые над ними, обеспечивая более объектно-ориентированное представление персистентного слоя

Репозиторий дает объектно-ориентированное представлениебазовые данные (которые в противном случае могут храниться в реляционной БД).Он отвечает за отображение вашей таблицы в вашей организации.

Генерация идентификатора для объекта является совершенно другой обязанностью ... вы можете решить создать этот идентификатор в БД, в Домене или в отдельной Службе.Независимо от того, где сгенерирован идентификатор, репозиторий должен плавно отобразить его между вашей сущностью и таблицей.

Генерация идентификатора является ответственностью его собственных, и если вы добавляете его в репозиторий, то вы нарушаете Принцип единой ответственности .

1 голос
/ 18 апреля 2019

Там уже есть отличный ответ на вопрос, я просто хочу добавить некоторые из моих мыслей.(Он будет содержать некоторое дублирование из предыдущего ответа, поэтому, если это плохо, просто дайте мне знать, и я его удалю :)).

Ответственность генерации идентификатора можетпринадлежат к другой части организации или системы.

Иногда идентификатор генерируется с помощью специальных правил, таких как Номер социального страхования .Этот номер можно использовать для идентификатора Person в системе, поэтому перед созданием объекта Person этот код необходимо будет сгенерировать из определенной службы SSNGenerator ,

Мы можем использовать случайный сгенерированный идентификатор, например, UUID.UUID могут быть сгенерированы вне репозитория и назначены объекту во время создания, а репозиторий будет только сохранять (добавлять, сохранять) его в БД.

Идентификаторы, генерируемые базами данных, очень интересны.Вы можете иметь последовательные идентификаторы , как в RDBMS, UUID-иш, как в MonogoDB или какой-то хэш.В этом случае Ответственность генерации идентификатора присваивается БД, поэтому это может произойти только после сохранения сущности, а не при ее создании.(Я позволяю себе свободу здесь, поскольку вы можете сгенерировать ее перед сохранением транзакции или чтением последней и т. Д., Но мне нравится обобщать здесь и избегать обсуждения случаев с условиями гонки и коллизиями).Это означает, что ваша сущность не имеет идентификатора до завершения сохранения.Это хорошо?Конечно Это зависит :)

Эта проблема является отличным примером неплотных абстракций .

Когда вы внедряете решение, иногда используемая технология влияет на него.Вам придется иметь дело с тем фактом, что, например, идентификатор генерируется вашей базой данных, которая является частью вашей инфраструктуры (если вы определили такой уровень в своем коде).Вы также можете избежать этого, используя s UUID, даже если вы используете RDBMS, но тогда вам нужно присоединиться к (опять-таки, к конкретным технологиям :)) на этих идентификаторах, поэтому иногда людям нравится использовать значение по умолчанию.*

Вместо Добавить или AddAndCreate вместо него можно использовать Сохранить метод, который выполняет то же самое, но это просто другой термин, который предпочитают некоторые люди.Репозиторий действительно часто определяют как « в коллекции памяти », но это не означает, что мы должны строго придерживаться его (это может быть полезно сделать в большинстве случаев, но все же...).

Как уже упоминалось, если ваша база данных генерирует идентификаторы, репозиторий кажется хорошим кандидатом для назначения идентификаторов (до или после сохранения), потому что это тот, кто общается с БД.

Если вы используете события, способ генерации идентификаторов может повлиять на ситуацию.Например, допустим, вы хотите иметь UserRegisteredEvent со свойством UserID в качестве свойства s.Если вы используете БД для генерации идентификаторов, вам сначала нужно будет сохранить Пользователь , а затем создать и сохранить / отправить событие или сделать что-то в этом роде.С другой стороны, если вы сгенерируете идентификатор заранее, вы можете сохранить событие и сущность вместе (в транзакции или в том же документе не имеет значения).Иногда это может быть сложно.

Фон, опыт работы с технологиями и основами, знакомство с терминологией в литературе, школе и работе влияет на то, как мы думаем о вещах и какая терминология звучит для нас лучше.Также мы (большую часть времени) работаем в командах, и это может повлиять на то, как мы называем вещи и как их реализуем.

...