https://kotlinlang.org logo
#android
Title
# android
c

Cyberpunk Keanu

01/04/2020, 9:42 AM
Best NoSQL database library for Multi-module Clean Architecture project? Hello folks, I'm having a hard time trying to find a NoSQL database library, which can work with multiple modules that get created (presentation, data, domain) by following the clean architecture pattern. I'd normally use Objectbox if the project specification doesn't necessarily has to be in Clean Architecture. If you have worked on any of your Projects in Clean Architecture pattern with multiple modules, then what databases have you used? 🤔
w

wasyl

01/04/2020, 11:39 AM
Clean Architecture explicitly doesn’t care what library you’ll use for your database/anything else. You mention multiple modules, but also presentation/data/domain — only of those should be concerned with specific library used
c

Cyberpunk Keanu

01/04/2020, 11:43 AM
I understand that, but the problem here lies within the way some of these libraries work. And most of them don't support multi-module projects. As I said, for a single module project I'd prefer to use Objectbox, but it doesn't support Multi-module project, so that's a huge bummer for me 😔 Hence, searching for alternatives that can work well with multi-module project while at the same time acknowledges & respects the S.O.L.I.D. principles in clean architecture
w

wasyl

01/04/2020, 8:47 PM
The only reason for any “multi-module support” would be if you wanted to declare e.g. Objectbox models in multiple modules. That’d mean you plan on having several data-layer modules with Objectbox, one for each feature for example?
Even then it’d be possible to use any library, really. I can’t quite find an example of where Clean Architecture prevents you from using any library
c

Cyberpunk Keanu

01/06/2020, 6:30 AM
But it does because of the library. For context, here's how you create an Object box db You declare project dependency, then apply the plugin in the module's build.gradle file. Now to work with Object box, you need an object 'boxStore' which is generated by the builder class MyObjectBox. This class is generated at compile time & will only be generated if there's atleast one @Entity annotated data class in the same module! Now, following clean architecture's abstraction, if all my data entities objects are to be in the domain module, but the MyObjectBox class need an applicationcontext to be passed to build it. So it has to be in the presentation module always. But the presentation module has no @Entity annotated data classes, so this MyObjectBox builder class will not be generated at compile time! Are you getting the point now, that implementation depends on the library itself as well?
w

wasyl

01/06/2020, 8:47 AM
Seems to me you make couple of wrong assumptions:
all my data entities objects are to be in the domain module
That’s not accurate, your domain models should be in domain module. Any data entities coupled to libraries specifically must not be in domain module
MyObjectBox class need an applicationcontext to be passed to build it. So it has to be in the presentation module always
Also not accurate,
presentation
should only concern itself with presentation, as its name suggests. Think of it like this: clean architecture promises that e.g. database library is abstracted away in such a way, you could easily swap it at later point. If your domain uses object box models, and your presentation uses objectbox classes, it means objectbox is coupled with all layers of your application and is not swappable at all!
So in clean architecture as I know it, none of those problems exist: -
domain
module has your domain models, e.g.
Post(id, author, text)
-
domain
module also has your data access interface:
interface PostRepository { fun getPosts(): List<Post>; fun getPostsByAuthor(author): List<Post>
-
data:objectbox
module has objectbox specific implementation, including models (like
@Entity PostEntity
) and repository class (
class ObjectBoxPostsRepository(MyObjectBox): PostsRepository
). -
objectbox
module depends on Object box library and on
domain
module.
domain
module doesn’t depend on anything - presentation has no dependency on objectbox module, instead
domain
module exposes some ways for presentation to act on
PostsRepository
(for example use cases, commands/queries etc)
Now
ObjectBoxPostsRepository
will retrieve entities from object box, map it to domain objects and return. This way domain doesn’t know anything about the library used. Last step for all of this to work is to use a dependency injection framework (or do everything manually) and whenever a domain class depends on
PostsRepository
, it will have
ObjectBoxPostsRepository
passed at runtime. I’d typically use Dagger and have the configuration in
app
module
I know that clean architecture allows library-specific metadata in the domain, since it’s just metadata. But a) I feel it’s a shortcut, and if the library doesn’t work well with it, it shouldn’t be used, and b) it’s a slippery slope and it’s much easier to accidentaly leak database implementation details to the domain, like using properties of type needed by the library, not type dictated by the domain
67 Views