Подтвердить что ты не робот

Является ли контент-провайдер реализацией шаблона репозитория?

Шаблон репозитория определен Хиеттом и Робом Ми как шаблон проектирования, который является посредником между доменом и слоями отображения данных, используя подобный коллекции интерфейс для доступа к объектам домена.

MSDN Repository Pattern

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

В чистой архитектуре Android Fernando Cejas все данные, необходимые для приложения, поступают с этого уровня через реализацию репозитория (интерфейс находится на уровне домена), который использует шаблон репозитория со стратегией, которая на фабрике выбирает разные источники данных в зависимости от определенные условия.

Content Provider

Однако, как отметил профессор Дуглас Шмидт на курсе Coursera, поставщик контента управляет и обеспечивает доступ к центральному хранилищу данных для одного или нескольких приложений.

Content Provider

В книге " Программирование Android" поставщики контента используются в качестве фасада для веб-службы RESTful. Этот подход был первоначально представлен Вирджилом Добянским во время Google I/O 2010.

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

enter image description here

4b9b3361

Ответ 1

Попробуйте сравнить определение шаблона репозитория из книги "Шаблоны архитектуры корпоративных приложений" Мартина Фаулера (с Дейвом Райсом, Мэтью Фоеммелем, Эдвардом Хияттом, Робертом Ми и Рэнди Стаффордом) с тем, что мы знаем о ContentProviders.

В книге говорится:

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

Важный бит accessing domain objects. На первый взгляд кажется, что шаблон репозитория предназначен только для доступа (запросов) данных. Однако с помощью ContentProvider вы можете не только получать доступ (чтение) данных, но также вставлять, обновлять или удалять данные. Однако в книге говорится:

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

Итак, да, репозиторий и ContentProvider, похоже, предлагают одни и те же операции (очень высокий уровень точки зрения), хотя в книге явно указано simple collection of objects, что неверно для ContentProvider, поскольку для него требуются специфические андроиды ContentValues и Cursor от клиента (который использует определенный ContentProvider) для взаимодействия с.

Кроме того, в книге упоминаются domain objects и data mapping layers:

A Репозиторий Промежуточное взаимодействие между слоями отображения домена и данных

и

Под обложками репозиторий объединяет метаданные (329) с объектом запроса (316) Отображение метаданных содержит детали объектно-реляционного сопоставления в метаданных.

Отображение метаданных в основном означает, например, как сопоставить столбец SQL с полем класса java.

Как уже упоминалось, ContentProvider возвращает объект Cursor из операции query(). С моей точки зрения, курсор не является объектом домена. Более того, сопоставление от курсора к объекту домена должно выполняться клиентом (который использует ContentProvider). Поэтому сопоставление данных полностью отсутствует в ContentProvider с моей точки зрения. Кроме того, клиенту, возможно, придется использовать ContentResolver, чтобы получить объект (данные) домена. По-моему, этот API является явным противоречием с определением из книги:

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

Затем давайте сосредоточимся на основной идее шаблона репозитория:

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

ContentProvider требует URI (строка). Так что это не "объектно-ориентированный путь". Также ContentProvider может понадобиться projection и where-clause.

Итак, можно утверждать, что строка URI является своего рода инкапсуляцией, поскольку клиент может использовать эту строку вместо написания конкретного кода SQL, например:

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

ContentProvider с использованием URI (строки), похоже, не противоречит этому определению, но все же пропускает подчеркнутый объектно-ориентированный подход. Кроме того, строки не являются объектами критериев повторного использования, которые могут быть повторно использованы в общем виде для составления спецификации критериев для "уменьшения количества кода, необходимого для обработки всех запросов, которые продолжаются".

Например, чтобы найти объекты людей по имени, мы сначала создаем критерии объект, устанавливая каждый отдельный критерий следующим образом: criteria.equals(Person.LAST_NAME, "Fowler" ) и criteria.like(Person.FIRST_NAME, "M" ). Затем мы вызываем repository.matching(критерии) для возврата списка объектов домена представляющие людей с фамилией Фаулер и имя начиная с M.

Как вы уже сказали (в своем вопросе), репозиторий также полезен для скрытия разных источников данных в качестве детали реализации, о которой клиент не знает. Это верно для ContentProviders и указано в книге:

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

и

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


Итак, чтобы заключить: некоторые определения от Мартина Фаулера и др. сопоставьте API API ContentProvider (если вы игнорируете тот факт, что книга подчеркнута объектно-ориентированной):

  • Скрывает тот факт, что репозиторий /ContentProvider имеет разные источники данных
  • Клиенту никогда не приходится писать запрос в DSL, подобном источнику данных, например SQL. Это верно для ContentProvider, если мы рассматриваем URI как не специфичный для источника данных.
  • Оба, репозиторий и ContentProvider имеют один и тот же набор операций "высокого уровня": чтение, вставка, обновление и удаление данных (если вы игнорируете тот факт, что Фаулер много обсуждает объектно ориентированную и коллекцию объектов, тогда как ContentProvider использует Cursor и ContentValues)

Однако ContentProvider действительно пропускает некоторые ключевые моменты шаблона репозитория, как описано в книге:

  • Так как ContentProvider использует URI (также строку для предложения where), клиент не может повторно использовать объекты Matching Criteria. Это важно отметить. В книге четко сказано, что шаблон репозитория полезен "В большой системе со многими типами объектов домена и множеством возможных запросов репозиторий уменьшает количество кода, необходимого для обработки всех запросов". К сожалению, ContentProvider не имеет объектов Criteria, таких как criteria.equals(Person.LAST_NAME, "Fowler"), которые могут быть повторно использованы и использованы для составления согласованных критериев (поскольку вам нужно использовать строки).
  • ContentProvider пропускает полное сопоставление данных при возврате Cursor. Это очень плохо, потому что клиент (который использует ContentProvider для доступа к данным) должен выполнить сопоставление Cursor с объектом домена. Кроме того, это означает, что клиент имеет знания о внутренних хранилищах репозитория, таких как имя столбцов. "Репозиторий может быть хорошим механизмом для улучшения удобочитаемости и ясности в коде, который широко использует запросы". Это, конечно же, неверно для ContentProviders.

Нет, ContentProvider не является реализацией шаблона репозитория, как определено в книге "Шаблоны архитектуры корпоративных приложений", поскольку он пропускает как минимум две существенные вещи, о которых я говорил выше.

Кроме того, обратите внимание, что, как уже говорилось в названии книги, шаблон репозитория предназначен для использования в Enterprise Application, где вы выполняете множество запросов.

Разработчики Android склонны использовать термин "шаблон репозитория", но на самом деле не означают "оригинальный" шаблон, описанный Fowler et al. (высокая повторяемость Criterias для запросов), а скорее означает интерфейс, чтобы скрыть базовый источник данных (SQL, Cloud, что угодно) и сопоставление объектов домена.

Подробнее здесь: http://hannesdorfmann.com/android/evolution-of-the-repository-pattern

Ответ 2

Короткий ответ: Contentprovider - это источник данных, а не репозиторий.

Цель SQL-Database/Android-Contentproviders/Repositories - создавать/читать/обновлять/удалять/находить данные

Хранилища обычно работают на определенных классах Java (например, Customer, Order, Product,...) в то время как SQL-Database и Android-Contentproviders работают на таблицах, строках и столбцах низкого уровня в качестве источника данных.

Поскольку SQL-база данных не является репозиторием, поэтому Android-Contentprovider не является репозиторией.

Но вы можете реализовать репозиторий, используя базовый Contentprovider

Ответ 3

Я упомянул Dianne Hackborn (из группы Android Framework), чтобы выразить свое мнение.

ContentProvider

Наконец, ContentProvider является довольно специализированным средством для публикации данных из приложения в другие места. Люди обычно думают о них как о абстракции в базе данных, поскольку для этого общего случая существует много API и поддержки, встроенных в них для этого общего случая... но с точки зрения дизайна системы, это не их точка.

То, что они представляют для системы, является точкой входа в приложение для публикации именованных элементов данных, определенных схемой URI. Таким образом, приложение может решить, как он хочет сопоставить данные, которые он содержит, с пространством имен URI, передавая эти URI другим объектам, которые могут, в свою очередь, использовать их для доступа к данным. Есть несколько особенностей, которые это позволяет системе управлять приложением:

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

• Эти URI также предоставляют важную мелкозернистую модель безопасности. Например, приложение может поместить URI для изображения, которое оно имеет в буфере обмена, но оставьте его контент-провайдера заблокированным, чтобы никто не мог свободно обращаться к нему. Когда другое приложение вытаскивает этот URI из буфера обмена, система может предоставить ему временное "разрешение на предоставление URI", чтобы разрешить доступ к данным только за этим URI, но ничего больше в приложении.

Что нас не волнует:

На самом деле не имеет значения, как вы реализуете управление данными за контент-провайдером; если вам не нужны структурированные данные в базе данных SQLite, не используйте SQLite. Например, вспомогательный класс FileProvider - это простой способ сделать сырые файлы в вашем приложении доступными через поставщика контента.

Кроме того, если вы не публикуете данные из своего приложения для других пользователей, нет необходимости вообще использовать контент-провайдер. Это правда, из-за различных помощников, построенных вокруг поставщиков контента, это может быть простой способ поместить данные в базу данных SQLite и использовать его для заполнения элементов пользовательского интерфейса, таких как ListView. Но если любой из этих вещей делает то, что вы пытаетесь сделать более сложным, тогда не стесняйтесь не использовать его и вместо этого используйте более подходящую модель данных для своего приложения.

Полный текст здесь: https://plus.google.com/+DianneHackborn/posts/FXCCYxepsDU

Ответ 4

Престижность в вопросе, это замечательное замечание:). ИМХО, это не вопрос "да" или "нет", потому что он довольно общий, так как большинство шаблонов, связанных с шаблонами дизайна. Ответ зависит от того, какой контекст вы принимаете во внимание:

Если у вас есть приложение, которое полностью полагается на платформу, что означает, что учитывайте только контекст экосистемы Android, тогда да, ContentProvider IS - это реализация шаблона репозитория. Аргументом здесь является то, что поставщик контента был разработан для решения некоторых из тех же задач, которые решают проблемы репозитория:

  • Он обеспечивает абстракцию над уровнем данных, поэтому код не обязательно зависит от среды хранения.
  • Нет прямого доступа к данным со всех сторон. Вы можете поместить все ваши SQL-запросы (или что-то еще) в одном месте. Когда я впервые реализовал ContentProvider как noob, это было похоже на откровение для меня, насколько чистый мой код может выглядеть и насколько комфортно я могу делать изменения.
  • Централизует данные и делится ими между несколькими клиентами (другие приложения, виджет поиска, как вы уже знаете) и обеспечивает механизм защиты данных
  • Вы можете определенно определить поведение, связанное с данными (одним способом является использование ContentObserver)
  • Это довольно хороший способ заставить вас с ранних этапов организовать ваш код с модульным тестированием/автоматическим тестированием.

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

Теперь, учитывая, что приложение работает в более крупном масштабе в нескольких средах (т.е. в Интернете, на мобильных ПК), требования полностью меняются. Это плохая идея, поскольку все предлагали полагаться на ContentProvider как шаблон дизайна. Это не обязательно плохая идея сама по себе, но шаблон дизайна должен быть реализован, чтобы другие могли понять ваш код как можно быстрее. Видите ли, даже здесь все предлагали использовать ContentProvider в общем виде: как источник данных, так или иначе зависящий от платформы. Поэтому, если вы принудительно выполняете реализацию поверх компонента с известной целью, все может стать довольно неясным. Гораздо лучше организовать свой код в классическом шаблоне.

tl; dr; Если ваше приложение изолировано на вашем устройстве Android, вы можете определенно объединить две концепции. Если ваше приложение используется в более широком масштабе, на нескольких платформах оно чище, чтобы упорядочить ваш код классическим способом.

Ответ 5

Это интересный вопрос. Я думаю, что мой первый ответ не будет, поставщик контента не является реализацией шаблона репозитория.

Как вы упомянули, шаблон хранилища предназначен для ветки бизнес-логики (домена) от уровня данных. Этот подход позволяет вам создавать модульные тесты для вашей бизнес-логики (так что домен вообще не должен зависеть от Android). Используя Content Provider, вам нужно будет иметь какие-то объекты Android в вашем домене.

Вы могли бы представить себе способ скрыть логику Content Provider за интерфейсом, но вы потеряете многие из приятных вещей, которые позволяет вам использовать Content Provider.

Если вас интересует архитектура Android, я бы порекомендовал вам взглянуть на этот проект Github Android Clean Architecture. Вы найдете отличный способ разделить уровень презентации, домена и данных, а связь между доменом и данными выполняется с использованием шаблона репозитория.

Надеюсь, это поможет!

Ответ 6

IMHO, лучше рассмотреть Contentprovider как источник данных, хотя данные можно хранить несколькими способами (база данных SQLite, файлы...), чтобы сохранить определенную независимость между архитектурой и каркасом Android.

Репозиторий Google предоставляет некоторые образцы архитектуры. Один из них содержит пример архитектуры с поставщиком контента и репозиторием:

googlesamples/android-architecture/todo-mvp-contentproviders

Выбранные выдержки:

Затем вы можете использовать контент-провайдеров для поддержки дополнительных функций, которые не охвачены этим образцом, обеспечивая следующие возможные преимущества:

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

архитектура todo-mvp-contentproviders

Ответ 7

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

Ответ 8

Проблема с использованием ContentProviders как репозитория заключается в том, что вы добавляете зависимость в своей модели к платформе Android. Использование шаблонов репозитория позволяет легко издеваться, тестировать и заменять реализации.

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

В основном, ContentProvider - это источник ввода-вывода, который вы хотите абстрагировать.