Работа с паттерном Repository

162
31 декабря 2021, 00:10

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

Можно было бы сделать как то так:

interface DataRepository extends DataSaveRepository, DataGetRepository {
}
interface DataSaveRepository {
     Boolean saveData(Data dt);
}
interface DataGetRepository {
     Data getData();
}

Реализация локального репозитория

class LocalRepository implements DataRepository {
     @Override
     Data getData(){
          //получаем данные из локальной БД
     }
     @Override
     Boolean saveData(Data dt){
           //сохраняем данные в локальную БД
     }
}

Реализация внешнего репозитория 1

class NetworkRepository implements DataGetRepository {
     @Override
     Data getData(){
          //получаем данные из интернета
     }
}

Вроде бы и логичнее так, а вроде и хр@нь какая то..

Или так:

Как я себе это представляю:

interface DataRepository {
     Data getData();
     Boolean saveData(Data dt);
}

Реализация локального репозитория

class LocalRepository implements DataRepository {
     @Override
     Data getData(){
          //получаем данные из локальной БД
     }
     @Override
     Boolean saveData(Data dt){
           //сохраняем данные в локальную БД
     }
}

Реализация внешнего репозитория 1

class NetworkRepository implements DataRepository {
     @Override
     Data getData(){
          //получаем данные из интернета
     }
     @Override
     Boolean saveData(Data dt){
           //сервер не предоставляет метода сохранения, с сервака можем только получать
     }
}

А объекты которые нуждаются в информации о профиле знают только об интерфейсе DataRepository и никак не зависят от реализации.

Как такие ситуации решаются(когда невозможно реализовать метод интерфейса)? Возвращать throw new Exception("not impl") или false?

Или уже совсем по другому спроектировать интерфейсы для репозиториев?

OffTop Нашел в англоязычном интернете статью в котором пишут что не нужно делать методы SAVE, Update в репозиториях, но я с этим не совсем согласен.

Answer 1

Можно использовать подход Clean Architecture - разделить приложение по слоям (своя ответственность и изолированность)

Например, запрос "дай профиль" исходит из слоя View (Presenter/ViewModel или что-то еще), этот запрос идет на слой бизнес логики (UseCase/Interactor/Domain или что-то еще), этот уровень должен знать откуда запрашивать профиль. Предположим профиль можно получить только извне, тогда обращение передается на следующий уровень, назовем его условно Repo - этот уровень, формирует запрос соответствующий API внешней системы, получает ответ и конвертирует его в понятный для бизнес уровня объект и возвращает его. Далее бизнес логика может преобразовать полученный профиль в какую-то иную форму, понятную слою View.

В вашем случаем, поскольку профиль нужно сохранять, то бизнес логика может инжектить два Repo - один для работы с локальными данными, второй - удаленными. Таким образом, получив запрос из View слоя бизнез логика, может сначала запросить локальные данные, если их нет, запросить данные извне, получить их, сохранить в локальный репо и вернуть на уровень View.

Ошибки могут носить разный характер - относящиеся к конкретному бизнес процессу и прочие. Где обрабатывать решать Вам. Очевидно, что ошибки бизнес логики, должны обрабатываться на уровне бизнес логики и преобразоваться в понятные ошибки текущего бизнес процесса. А например, отвалился/недоступен по тайм-айту сервер, должны обрабатываться в общем виде.

Таким образом, View/Domain/Repo ничего не знают о работе друг друга, только используют их внедренные объекты, используя интерфейсно доступные методы.

READ ALSO
Не работает repaint в JPanel

Не работает repaint в JPanel

Всем приветПроблема такова

145
как в sql добавить нули перед числом

как в sql добавить нули перед числом

есть поля которое может принимать четырехзначные числа если он 25 добавить два нуля перед числом если 9 то три нуля а если 123 то 1 нол как сделать

115
Java шифрование

Java шифрование

помогите пожалуйста что я нет так делаю ?

167