Имеет ли смысл использовать шаблон хранилища с базой данных документов? - PullRequest
23 голосов
/ 21 сентября 2011

Я сейчас экспериментирую с MongoDB .Я перехожу с NHibernate / SQL мышления, и поэтому изначально я реализовал шаблон хранилища для доступа к данным.

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

Успешно ли люди используют шаблон репозитория с базами данных документов?Если нет, то какую методологию доступа к данным вы используете?А как насчет абстракции / SoC?

Ответы [ 5 ]

14 голосов
/ 11 февраля 2012

Это интересный вопрос.В моем использовании MongoDB я решил не иметь хранилище.Это было первично, потому что база данных документов использовалась в качестве хранилища для чтения (поэтому упростила данные, которые там хранились).

Полагаю, вам нужно отбросить вопрос о том, что такое репозиторий и какие преимущества вы получаете отдополнительный слой абстракции.Хороший дизайн будет иметь наименьшее количество слоев возможных .

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

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

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

2 голосов
/ 13 февраля 2012

Я использую MongoDB в производственном коде с шаблоном репозитория уже более 2 лет, и могу сказать, что со временем он мне действительно помог. Абстракции хорошо подходят для тестирования (в памяти) и производства (MongoDB).

Я использую Java, и код выглядит примерно так (примерно):

public interface MyStorage {

    boolean add(MyDoc doc);

    boolean update(MyDoc doc);

    boolean remove(String docId);

    boolean commit();

    MyDoc get(String docId);

    MyStorageQuery newQuery();

    List<MyDoc> query(MyStorageQuery q);

}

У меня есть фабрика для каждой реализации хранилища, которая создает новые экземпляры объекта MyDoc. Я поменяю местами реализацию между MongoDb и моей собственной ручной проверкой для тестирования.

Реализация MongoDB использует класс MyDoc, который расширяет BasicDBObject следующим образом:

public interface MyDoc {
  Data getData(); // let's assume this is a nested doc
  void setData(Data d);
  String getId();
  long getTimestamp();
  void setTimestamp(long time);
}

MongoDbMyDoc extends BasicDBObject implements MyDoc {
  MongoDbObject() { }
  void setId(String id) {
    this.put("_id", id);
  }
  String getId() {
    return super.get("_id");
  }
  void setData(Data d) {
    dataObj = new BasicDBObject();
    dataObj.put("someField",d.someField);
    dataObj.put("someField2", d.someField2);
    super.put("data",dataObj);
  }
  ...
}

Затем я в реальной реализации хранилища использую Java-клиент MongoDB для возврата экземпляров моей реализации из БД. Вот конструктор для моей реализации хранилища MongoDB:

public MongoDbMyStorage(DB db, String collection) {
  //DB in a mongodb object (from the client library) which was instantiated elsewhere
  dbCollection = db.getCollection(collection);
  dbCollection.setObjectClass(MongoDbMyDoc.class);
  this.factory = new MongoDbMyDocFactory();
}

Здесь есть еще 2 интерфейса: MyStorageQuery, который также реализован как BasicDBObject для реализации MongoDB и сгенерирован с использованием newQuery() интерфейса хранилища. И MyDocFactory, который здесь не представлен, но в основном это фабрика документов, которая знает, что такое реализация хранилища, и соответственно генерирует экземпляры MyDoc.

Предостережения:
Одна вещь, где абстракция не имеет особого смысла, это определение индексов, используемых хранилищем MongoDB. Я поместил все свои ensureIndex(...) вызовы в конструктор, не очень общий, но определение индексов для коллекции - это специфическая оптимизация MongoDB, поэтому я могу с этим жить.
Другое - это то, что коммит реализован с помощью команды getLastError(), которая по моему опыту не сработала так хорошо. Для меня это не проблема, так как я почти никогда не фиксирую изменения явно.

2 голосов
/ 13 февраля 2012

Думать о «Должен ли я использовать X или нет» не так продуктивно, как сосредоточиться на «Что я должен использовать»?

Каковы альтернативы шаблону хранилища, каковы компромиссы и как они связаны с вашим доменом и реализацией?

Репозитории хороши для принудительного применения предопределенного набора шаблонов в хранилище общего назначения (например, SQL). Для хранилища документов у меня сложилось впечатление, что схема документа будет определять шаблоны доступа в большей степени, чем вы обычно видите в хранилище на основе SQL. Реализация репозитория в этом случае может привести к очень утечкам абстракций, где изменения в базовой структуре документа оказывают влияние 1: 1 на соответствующий бизнес-код. В этом случае хранилище дает очень мало значения. Для меня хранилища документов естественным образом поддаются парадигмам единиц работы (UoW), где единицей работы является документ (или doc + вложенные поддокументы, или наборы документов).

Другой сильной стороной шаблона хранилища является, как вы упомянули, абстракция над механизмом хранения. Компромиссом обычно является потеря доступа к низкоуровневым особенностям реализации Mongo. Это выгодный компромисс для вас? NHibernate очень тесно связан с SQL и, следовательно, имеет богато функциональные абстракции по всем важным функциям СУБД. Я не знаю какой-либо подобной структуры для Mongo, так что вы бы действительно немного повысили уровень абстракции.

Нужно ли вам поддерживать несколько одновременных хранилищ данных? Например, будете ли вы записывать некоторые типы данных в SQL, а другие - в Mongo через одну и ту же абстракцию уровня данных? Если это так, то хранилище является хорошим вариантом.

Если вы можете предоставить более подробную информацию о вашем домене и реализации, тогда мы можем подробнее изучить некоторые компромиссы, которые вы, возможно, захотите рассмотреть

2 голосов
/ 09 февраля 2012

Не знаю, поможет ли это вам, но я некоторое время назад слушал подкаст , в котором Айенде Рахиен говорила о RavenDB.Он предположил, что документ на самом деле довольно хорошо отображается в совокупности в философии DDD.Если вы используете вложенные документы для представления совокупности и сталкиваетесь с проблемами проектирования, возможно, вложение - не лучший способ?

0 голосов
/ 14 января 2012

Эрик Эвенс (Eric Evens) в своей книге «Управление управляемым доменом» имеет очень сложное и очень хорошее объяснение паттерна хранилища. Он определяет, каким должен быть репозиторий и как его использовать (по моему личному мнению). Краткое описание вы можете найти здесь: Эрик Эванс в репозиториях

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

...