0

I have this project with MVVM and clean architecture well implemented but I've decided to split it into modules. Right now I have: apimodule

  • apimodule: with the retrofit dependencies
  • app: with the data, domain and presentation layers.

I want to modularize it even more: Create a domain module with the domain models, usecases and repository interfaces. In theory, this module shouldn't depend on the data layer. Create a data module with the repositories and DataSources that depends on the apimodule (and eventually databasemodule) and the domain module. Move the activities and viewmodels to presentation module that only depends on the domain module.

So far so good. The problem starts when I try to add a DI library to the equation (I'm using Koin for this).

  • If I define the repository injection in the domain module, then it should depend on the repository module to retrieve the repository implementation.
  • If I define the injection in the data module, then I'm coupling presentation module to the data module, also making the repository interface useless.

I think the first approach is much better than the second one, but I don't like it either as it would violate the principle "Domain Layer does NOT depend on Data Layer".

0

Your Domain Module should define interfaces for all the repositories it needs. What you are calling your Repository Module should have public classes that implement the repository interfaces. Doing this keeps your domain classes free of any outside references. Any data the domain classes need will come from objects implementing the repository interfaces defined in the Domain Module.

The Repository Module certainly depends on the domain classes, but since the repositories implement interfaces defined in your Domain Module no direct references to the concrete repository classes should exist in your Domain Module.

If I define the injection in the data module, then I'm coupling presentation module to the data module, also making the repository interface useless.

Neither the Domain Module nor the Repository Module should have any knowledge about a dependency injection container. DI containers should be configured near the composition root of your application, e.g. the main method or some sort of "application" class. Any dependencies that should be passed to any of the domain or repository classes should be done so through constructor injection, thus eliminating references to DI classes in the domain and repository modules.

Create a data module with the repositories and DataSources that depends on the apimodule (and eventually databasemodule) and the domain module.

This seems a little over complicated to me. Creating a Repository Module makes sense, but then further splitting it into a Data Module, API Module and Database Module simply because the storage technology is different seems like unnecessary separation. There is nothing wrong with your Repository Module having knowledge about web APIs and database queries. This module's primary purpose is data storage and retrieval. Keep It Simple.

Move the activities and viewmodels to presentation module that only depends on the domain module.

Here again this might be unnecessary separation. Once you get to activities and view models code becomes application specific. Unless you need to reuse activities and view models in multiple applications keep them in the same module: the Application Module, if you will. Only when you see a need to reuse this code should you spin it off into its own module. YAGNI is your best friend here.

Creating a Presentation Module seems like overkill. So does creating API and Database Modules, and YAGNI again gives us some guidance. That being said, creating domain and repository modules makes perfect sense because it allows these to be decoupled, and facilitates testing.

| improve this answer | |
  • Hey, thanks. The repositories are in the data layer, so I'm basically talking about the same as you with a different name. And I'm following the principle of having the interfaces in the domain layer "Create a domain module with the domain models, usecases and repository interfaces." The thing is: if the implementation is in the data/repository module and the main module can't depend on the repository module, how is the DI library going to create the instance of the implementation? – kirchhoff Mar 6 at 17:00
  • @kirchhoff: There is the root of your problem. The "main" module, which is likely your application, should depend on the repository, domain and DI layers. That is your composition root. That is where everything begins. Push knowledge of all the dependencies as far as you can towards the application. – Greg Burghardt Mar 6 at 17:09
  • That would work definitely and I'm okay with it, but I was trying to follow this approach: proandroiddev.com/… and I've heard some folks are following it but I can't find any example (the repo provided in the article is a mess) – kirchhoff Mar 6 at 17:15
  • @kirchhoff: Remember that each "layer" in the diagram does not necessarily mean it is a separate module. It could be a separate group of classes, but those classes don't necessarily need to be in other JARs. – Greg Burghardt Mar 6 at 17:17
  • Of course, and they could all be in the same module. But I wish to know if it's possible to have one module per layer without coupling them (if it isn't, then okay for me and I will keep using your approach). – kirchhoff Mar 6 at 17:20

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.