1

I'm developing an Android app whose architecture is based on the well known Uncle's Bob Clean Architecture.

I have the following Use Case:

Validate User Subscription

It's based on this use case descryption( main success scenario)

  1. Check if validation warning was already shown

    • Yes -> Go to step 6

    • No -> Go to step 2

  2. Check if user has internet connection

    • Yes -> Access remote repository

    • No -> Access local repository

  3. System gets user's subscription hash in repository

  4. System generates a key to decrypt the subscription hash

  5. System decrypts the hash using the previously generated key and returns the status of the subscription ( Valid / Invalid)

    • Status is valid: System saves the subscription on device and changes the user type to Premium

    • Status is invalid: System saves the subscription on device changes the user type to Free

  6. Use case terminates

I'm facing a problem on step 2. As you can see, I need to change my repository during the use case execution, but I don't know the best way to implement it.

One of my ideas was to inject the repository through method injection ( using some sort of setRepository(Repository repository) instead of constructor injection. Is this ok?

  • 1
    What do you mean by "OK?" Note: don't answer that question with a tautology like "best practice." State a specific, objectively-answerable criteria. – Robert Harvey Nov 5 '16 at 18:57
  • Well, on the majority of examples about Clean Architecture that I saw/read the use case dependencies were injected during use case construction and not execution. Also, in my view I think that letting the use case choose the repository at execution time is bad for testing since the decision of which repository to use is inside the use case. – Rômulo.Edu Nov 5 '16 at 20:39
  • 4
    Why not inject a factory instead that will return the repository you need by passing it either 'local' or 'remote' as constructing arg ? – Steve Chamaillard Nov 7 '16 at 5:24
1

Try a proxy which has the remote and local repository as dependencies and use the one needed. Here is a C# implementation

public class ProxyRepository : IRepository

{
    private readonly IRepository _remoteRepository;
    private readonly IRepository _localRepository;

    public ProxyRepository(IRepository remoteRepository, IRepository localRepository)
    {
        _remoteRepository = remoteRepository;
        _localRepository = localRepository;
    }

    public byte[] GetUserHash(Guid userId)
    {
         if (ThereIsAnInternetConnection())
              return _remoteRepository.GetUserHash(userId);
         else
              return _localRepository.GetUserHash(userId);
    }

    private bool ThereIsAnInternetConnection()
    {
        // your implementation of this, you might want to cache this call
    }
}
  • 1
    In "clean architecture speak", this means moving the internet access check out of the Use Case and into a Gateway/Driver. This may or may not be OK, depending on if you consider "use the remote repository if there is internet access, the local repository otherwise" a business rule or not. – Jory Geerts Nov 7 '16 at 13:28
1

I know this is an old question but maybe I can help others that also come looking for this answer.

I think you're confusing Repositories with DataSources.

A Repository should represent a collection of objects, or a single object, as if it were always in memory.

In your example, you would have a UserSubscriptionRepository with a get() method. This repository would have two DataSources: RemoteUserSubscriptionDataSource and LocalUserSubscriptionDataSource. Each of these would know how to get the user subscription from a different source (maybe an API for the remote and a database for the local).

Then, the UserSubscriptionRepository would orchestrate how and when to use each of these DataSources (change the word repository for datasource in your step 2 and this turns into the implementation of your get() method).

Finally, your use case would call userSubscriptionRepository.get() and get the data it wants, not knowing where it came from (remote or local sources).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.