4

I need to implement pull to refresh in an iOS app, and I came across this thing, in where I don't know how to approach the problem with the best practices of DDD.

The presentation layer has an event to refresh a list, this needs to update the results throwing away the cache and fetching the elements from the backend.

In the Domain layer, my use case talks to a repository, but, since caching is an implementation detail, the repository interface does not expose a 'cleanCache' method, so there is no clean way to refresh cache from a use case. this is more or less the file structure that I have

Domain

  • GetAllTodosUseCase
  • TodosRepository (interface)

Infrastructure

  • InMemoryTodosRepository (cache)
  • RemoteTodosRepository (api)
  • InMemoryWithRemoteTodosRepository (composes cache and api)

Application

  • factories

Presentation

  • UI (talks to an interactor interface)

2 Answers2

1

Since it seems to be use case specific when it is okay use a cache and when the remote resources need to be fetched, the decision which repository to use best fits to the application layer.

You could use, for instance, a factory which provides the application use cases the concrete repository implementations at runtime, still being dependent on the repository interface only at compile time.

Or you create another repository interface with the same methods and explicitly bind this repository interface to the concrete use case which should use the cache.

Andreas Hütter
  • 3,288
  • 1
  • 11
  • 19
  • 1
    Hm.. I think Having 2 use cases here might be the right thing.. since they are actually 2 different use cases, one is getting the Todos, and the other one being Refreshing the todos Inside that Use case, they both probably call the same repository method, the only difference would be that the Application Layer decides which repository to inject on those different use cases. – Nicolas Frugoni May 21 '21 at 12:56
0

The UI invokes a controller that executes the use case. The controller is responsible for recognizing the user interaction and translating it to an appropriate invocation of the use case. Thus the controller must recognize the pull to refresh and just create a new use case and pass it an "uncached" repository.

Your controller code should contain something like this

 TodosRepository repository;

 if(isPullToRefresh()){
    repository = getRemoteTodosRepository(); 
 } else {
    repository = getInMemoryTodosRepository();
 }

 GetAllTodosUseCase usecase = new GetAllTodosUseCase(repository);
 
 List<???> todos = usecase.getTodos();
René Link
  • 48,224
  • 13
  • 108
  • 140
  • I don't think that having those if cases in the use case, nor the presentation layer makes a lot of sense. I think having 2 use cases, one for getting all and another for refreshing can make a bit more sense – Nicolas Frugoni May 21 '21 at 12:57