Where to place business logic in a Dagger/MVP app - android

Having looked at a lot of Dagger demo apps, it isn't clear to me where business objects are placed. In a typical three tier app you have ui, business layer and data access layer. MVP is essentially a three tier architecture.
Dagger deals with components and modules and I've seen demo apps place business logic in modules. But according to the MVP architecture, business logic belongs in the Presenter layer as this layers is suppose to act as bridge between the ui and model. Many of these demo apps have models that consist of nothing more than a class with public fields to store and retrieve data from.
Can someone clarify the proper way that this should be done.

Following clean architecture which was describe by Uncle Bob, all your code that contains business (domain) logic (rules) should be inside business layer.
For example we are developing mobile application for online ordering food / clothes. Does not matter.
Presentation Layer: (Consists of view and presenter)
- Presenter - handle view intents (button clicks, view rendered and etc), call business interactors, after received result from interactors, says to view to render current state of screen / layout.
- View - nothing more than render UI, keep view stupid, all your view logic should be in presenter.
Example case: In this layer you could check for example: user oped cart screen, your presentation layer makes request to interactor which returns cart items. If list is empty your view shows layout with title "Your card is empty", otherwise shows items list.
Business / Domain Layer: (Consists of interactor, helper classes and etc.)
Rule number one is keep your domain layer pure. If you using gradle you can use multi-modules with empty dependencies. Only language, rxjava cause it is almost standard of our time.
Example case: You need to validate user order information (delivery address, initial). All your logic should be here. Length check, regex validate and etc.
Data Layer:
Knows how to save, fetch, update, delete informations. All about persistence. In android cases: data layer could make http request via retrofit2, room orm and etc. Cache starts here.
If your app doesn't contain a lot of business rules, you could avoid business layer. It depends on the project.
Also important to use SOLID principles. It will make your architecture understandable, flexible and maintainable. Read more here.

Related

Does LiveData have to exist in the Repository?

I'm a beginner studying MVVM design patterns.
Looking at the code of Google CodeLab and other sample codes, a question arose.
As the title suggests, does LiveData necessarily exist in the Repository?
I've been using and observing LiveData in a ViewModel so far.
(There's no special reason, I just used it because I didn't know anything)
By the way, I looked at the code of Google CodeLab to study Room, and I saw that it uses LiveData (or Flow) in the Repository and reference this in LiveData of the ViewModel.
Sample code from other web sites was similar.
But I don't know why LiveData is in the Repository and uses the way it's referenced.
Since LiveData is used in the Repository in the code of official docs such as CodeLab, I am using it accordingly, but I do not know why.
In the MVVM pattern, does LiveData necessarily exist in the Repository? I'd appreciate it if you could explain why.
LiveData is simply an observable data holder. It is lifecycle aware so it is a good practice to use it for providing data to View from ViewModel. LiveData can now be replaced with Flow which have few benefits over LiveData.
From Repository to ViewModel, it is completely up to you whether you want a LiveData/Flow returned or simply return the model that you expect from DAO but still you will require a LiveData/Flow if you want to provide that model to View after receiving that model from Repository to ViewModel.
The MVVM pattern is more about designing software, and organising the architecture into separate layers. The View is the user-facing frontend, the Model is the backend where the data is handled.
The View Model sits between them, converting data from the Model into some form of UI state the View can display, and turning UI events like button presses into calls to the app's backend functions, in the Model.
LiveData and Flow (which are similar - one is Android and one is Kotlin) are ways of exposing data, which is ultimately what the Model does - producing data. Instead of just providing a single value on request, they're able to provide a stream of data.
And the View Model (which is the intermediary between the Model and View - they don't talk to each other) can take that LiveData or Flow, and either expose it directly to the View, or do some processing on it to produce data suitable for the View to display. That way you have a pipeline from the data producer (the Model) to the UI (the View). That's basically how MVVM works in general, this is just using the streaming/producer/reactive model to wire things up and make things like async operations simpler
This is worth a read, it explicitly mentions repositories as the data producer in this model:
https://developer.android.com/kotlin/flow

Can a use case be called in data layer in context of Clean Architecture?

I have read a couple articles about clean architecture concepts here and here and others.
I think I understand what is going on but they didn't solve the question that I have.
I wonder if a use case can be called from data layer. if so, how? if not why?
UPDATE:
what I am trying to do is to track what is happening during each usecase with a event usecase. Sometimes, I need to collect those info in data layer as well.
Let's say I have
CollectEventUseCase
for that event usecase. I want to track if a person data lookup from network was fail but successful from database during the LookupPersonUsecase and I want to collect that information that lookup was failed from network but successful from database, is this a bad idea to call CollectEventUseCase in data layer? is this okay solution to this case? or whatelse should be the right approach?
Short Answer - No, in a CLEAN architecture the data layer should not be calling through to a use case as it would be breaking the separation of concerns. Data layer should only be concerned with data, not business logic which lives in a use case.
Long Answer
One main reason for implementing a CLEAN architecture is for implementing separation of concerns, meaning each layer addresses a specific concern in your app. Expanding on the photo in domain layer Android documentation, an app architecture might look like the picture below.
Where the domain layer would contain all of the business logic for presentation and use cases which can communicate with different sources in the data layer.
The data layer exists to serve as an abstraction over where data is coming from and that should be its only responsibility. Most apps data layers are fetching data from the network and then caching that data in a local database. So to best separate the concerns, a use case should only be concerned about interacting with different sources from the data layer and any business logic.

Project structure issue (MVP): data layer

I write android app using MVP pattern. My question is regarding database layer. I want to make it maximally independent, so it will be possible to replace it with something else without code changing in Presenter in the future. I decided to use pure SQLite without ORM, since the user table is updated in different places with differenet fields (in some place I update user's name, in other place in code - token etc.). ORM (I used realm) doesn't allow to do it, you have to write separate method for updating name, separate - for token etc.
Another problem is with ContentValues: when you update user you have to specify the fields you want to change via ContentValues in Presenter, and then Presenter calls repository.updateUserLocal(contentValues), so my Presenter dependents on data layer (if I decided to add ORM to the project, I will need to go to every Presenter and remove ContentValues). So the architecture is bad. Can you please advice how to organize the architecture of the app in the best way?

Client Architecture - Data Layer, MV* and coupling

I've been researching best practices for client architectures for a while now, including mvvm and the latest additions such as flux...
I'm considering the architecture for an android app, which will probably use a combination of mvvm and mvp for presentational purposes.
The thing that troubles me is coupling between components (mv* related classes),
for example:
I have a SlimStockItem model used in StockListView, which enables navigation to a StockItem used in a StockItemView, StockItem has more data.
I could use the same StockItem with null values for both views - this would introduce coupling between the controllers and views of the list and item details components or using a different approach which results in a couple of implementation choices:
Have a "domain" entity called Stock which has all the data and construct the relevant StockItem from it's "repository"
Don't implement a domain layer at all and query the server for StockItem (implement caching if appropriate at a technical layer)
Keep the coupling and pass StockItem to the stock item view.
The second scenario is receiving an update (push/pull) for a Stock from the server.
(Flux) Events are really good as a pub/sub implementation to inform multiple view of new state changes originating from user interactions/server push/pull interactions.
When considering the implementation, I have couple of choices:
1. Update the "domain" layer and publish a downstream event "StockUpdated" with the "domain" model Stock as payload for the mv* components to update SlimStockItem and StockItem.
2. Don't implement a domain layer at all and publish an event "StockUpdated" with a StockDataPayload for the mv* components to update SlimStockItem and StockItem.
Which approach do you use and what are the potential tradeoffs? (If you use a different approach then please describe it!)
P.S i'm quoting "domain" model, because the actual domain model resides at the server and is out of scope when discussing client architecture.
Best regards,
Erik.

Android - Organizing Login fragment and MVC principles

By following basic tutorials I've created a login fragment that has a username textview, password textview, and button. It POSTS the login info to an API which validates the login. EVERYTHING i do is in the login fragment (controller).
I have 3 questions:
Following Model, View, Controller - I do not have a model. The View is the layout, and the controller is the fragment. Is this right?
I feel as if the login code should be broken down into more classes... such as separating out the post request from the rest of the code. If I were to move the asynchronous request to another class file, I would also have to pass the views needing to be hidden while attempting to validate the user. Is there a better way to accomplish this, or is it OK to leave the http request code in the login fragment?
Is there something I'm missing that might need to be in another class?
In my opinion, in Android you don't have typical MVC pattern like in some web applications. You can treat XML layouts as a views. It's provided by design of the Android API. Activity is the actual controller. If you have some complicated logic you can create separate classes, which will be responsible for that logic. Activity shouldn't be of course "God class" holding all the operations. You can store your models in a separate package as a POJO objects and access them via other classes responsible for logic of the application. You shouldn't keep HTTP requests in Activity or Fragment. You should move them to another class to separate logic responsible for displaying data from logic responsible for retrieving data. Fragments should be used only when it's necessary, but not all the time. You can use them, when you want to display dialog, use tabs in your layout or create adaptive layout for tablets and mobile phones. I think, if you don't really need fragments, you don't have to use them. You can read how Square is advocating against Android Fragments. You can deal with asynchronous requests with RxJava. You can return Observables and subscribe them every time you want to create asynchronous request. It gives you good granulation, separation and control over your code.
Of course, it's only my opinion based on some experiences and I may be wrong. I'm eager to hear opinion of other developers and their experiences.

Categories

Resources