I am using the Clean Architecture principle for my Android app.
I have a dashboard screen with two lists, one list with feeds, the other with events.
For this screen, I have a ViewModel that will contain the lists.
To provide the data to the ViewModel, I have a UseCase called ViewDashboardUseCase.
The UseCase makes use of two repositories, one for the feed entity and the other for the event entity.
Taking this information into account I have a few questions:
Is this the right approach to use the UseCase? Should I create two UseCases?
If I should use one UseCase, what is the best way to return the two lists from that UseCase and use them in the ViewModel.
At the 2017 Google Developer Days, Florina commented about separating your screen into what she called "logical units" and then observing these logical units on separate LiveData.
Basically, you would create two view states (or I believe, use cases, in your code) and then fill each view state with the list. Finally, expose these view state to your view using two LiveData.
Here's a video of the conference: https://www.youtube.com/watch?v=Ts-uxYiBEQ8
She starts talking about these around the 8 minute mark.
Should I create two UseCases?
Yes, you should use a UseCase per one Repository.
Depending on whether you need the lists to be "fed separately" (one at a time) or "combined" (simultaneously), the ViewModel might use either the two UseCases or a new UseCase combined of the two.
Related
I am developing a simple application.
The user navigates through the elements of the RecyclerView to the end screen.
When scrolling LastFragment to the very bottom of the fragment, the SharedPref saves the status to true. Then the next element becomes available.
LastFragment has a button that plays a sound when clicked
I'm trying to build an application according to the principles of clean architecture and
I don't understand where UseCase is. Could you explain to me which UseCase should be used here?
You need to have something like:
PersistEndWasReachedUseCase
Or whatever name you like that will call the: "SaveToSharePrefs" Logic.
They should be part of your Domain Layer:
https://developer.android.com/topic/architecture/domain-layer
But at the same time, you need to be clean. This means that your logic should not know where it saves states. It might be a DB, SharePrefs, a remote server, etc.
That is why you should you a repository pattern:
https://developer.android.com/codelabs/basic-android-kotlin-training-repository-pattern#0
https://www.raywenderlich.com/24509368-repository-pattern-with-jetpack-compose
So you need to also have a Data Layer:
https://developer.android.com/topic/architecture/data-layer
But long story short - what clean means - You put your business logic in the inner layers. They depend on interfaces declared in these layers. And then outside layers implement these interfaces.
Basically this is an Inversion of control. Check SOLID.
https://miro.medium.com/max/1400/1*B4LEEv0PbmqvYolUH-mCzw.png
As per the image - you push the implementation details: Room, SharedPrefs, etc in the outer layers. And the inner layers are pure Kotlin/Java code. It knows nothing about implementation details - they are hidden by interfaces.
I created a library here: https://github.com/chanjungkim/ALiveData
This library is made because of MutableLiveData<ArrayList<T>>. Many people who learns about LiveData complains or they are confused with this type when they need to manipulate(add, remove, etc) the MutableLiveData. That's because ArrayList is easy to manipulate and _arrayList.value!!.add(item) or _arrayList.value!!.remove(0) seems to notify. But they don't.
At the end, when we want to notify, we must assign a value like _arrayList.value!! = mList. ArrayList and List both need to set the data like _arrayList.value!! = mArrayList or _arrayList.value!! = mList.
My question is List doesn't have add(), remove(), etc. On the other hand, ArrayList already has those functions and helps us manipulate the list much easier.
some people suggested like this
_list.value = list.value.toMutableList().doWhatever().toList()
So, what's the point of using List over ArrayList? Could you give me example with the explanation of using it?
LiveData can be used in different ways, and of course there is no one correct way, but a very common way of using it is within the Android MVVM architecture recommended by Google for use in Android apps.
In this architecture, the Activity (or Fragment) observe the LiveData of the ViewModel. When doing this, the goal would be to make the UI as 'dumb' as possible, where you try to handle as much of the app logic and behaviour in the ViewModel, and the Activity simply observes and reflects it on the UI.
In a case like this, it is often preferable for the values of the LiveData being observed to be immutable.
By doing this, it limits the Activity from being able to manipulate the data it is observing, such as add()ing or remove()ing anything from it. As just described, the goal should be to limit the UI's ability to make exactly these type of changes. If the Activity wants to add() an item to an ArrayList that it is observing, it should instead do this by calling a method on the ViewModel, which will in turn update it's own LiveData.value to the new, updated list, which will in turn be observed by the Activity and updated on the UI.
By only allowing the Activity to observe the immutable values, it helps enforce this separation of concerns, and limits any accidental 'leak' of logic into the Activity itself.
This idea can be extended further by ensuring that the observed values are of type LiveData, and not MutableLiveData. Using the latter can allow the Activity to manipulate the live data on its own, and break the MVVM pattern.
A List is an interface, and defines the methods that must be implemented by any classes that would like to behave like a list. It can be considered the 'most basic' version of a list, and only defines the minimum requirements for an implementing class to behave like a list.
In the same way, the List interface itself extends the Collections interface, which in turn extends the Iterable interface. Each one adds more functionality to the one before it... kind of like lego blocks stacked on top of each other, creating more complex shapes.
An ArrayList is a class, which implements MutableList (which itself implements List). This means that an ArrayList can be instantiated, and passed around as an actual object. Because of this object oriented design, and according to the Liskov substitution principle, any class (or interface) can be replaced by a subclass (or class implementing the interface) interchangeably.
This is a fundamental principle to object oriented design. It helps break parts of the application down into smaller, more basic and more manageable pieces, and then grow as required.
To answer your question more specifically, if the class that is observing the LiveData only cares about the methods defined in the List interface, then that is the all it requires to know about the value. The actual value could in fact be an ArrayList, a MutableList or even a custom class MyOwnFancyList<E>: List<E>, it does not matter to the observer, just as long as it implements the List interface.
I'm working on an android app in Kotlin that has user profiles, and I'm trying my best to code as clean as possible, using MVVM. While working on the part responsible for updating user's profile, I noticed that the model (POJO), viewmodel and the fragment itself are 90% similar with the ones responsible for registering the user. My question is what design should I choose and why:
make the 2 actions separate, respecting the single responsibility principle, but have a lot of duplicate code
merge them into one single action (one viewmodel, model and fragment), with some extra if's here and there
Or is there another way? Maybe with interfaces? Inheritances? How should one implement this?
MVVM has three strong part for clean way coding. VIEW - MODEL - ViewModel
Your fragment will be VIEW for showing profiles and taking action from user
ViewModel will be for calculating or manipulating profiles data
Model/Repo for generating/getting profiles data from or to server/storage
Fragments <-> ViewModel <-> Repo/Model
Use inheritance to keep the common code in a basefragmet / viewmodel . So you have :
UserProfileUpdateFragment -> UserProfileFragment
UserProfileRegisterFragment -> UserProfileFragment
or
UserProfileUpdateVM -> UserProfileVM
UserProfileRegisterVM -> UserProfileVM
I have been reading about MVVM pattern. View is supposed to observe for changes in ViewModel and act on it accordingly but I am confused if following code in View is ok in MVVM architecture.
fun onClick(view:View){
showUser(viewModel.getUserDisplayName())
}
Here View is not observing for a change, its rather asking for latest data from ViewModel. Is this considered correct in MVVM?
This is a question that possibly has no one answer, as different points might be made depending on the exact use case. However:
Sir Codesalot (great handle) is in my opinion technically correct. Let me elaborate.
In MVVM the view should pass UI interaction events (commands) to the ViewModel.
Here is an article from microsoft (who invented mvvm): https://msdn.microsoft.com/en-us/library/ff798384.aspx
The examples here are not related to android, but the concepts should be the same, especially if you look at the first diagram.
The ViewModel should do its magic, react to these events by manipulating data accordingly and then notify the observers (usually the view) of state changes. The view then reacts to the state changes.
In this way, if you would just pass data back from the ViewModel (in a synchronous way), then your view might be missing side effects. In your particular example, there probably aren't any, but consider that the method you call does not only return data, but also changes some internal state (e.g. counts the number of times the data was accessed). Then your view will not know of these.
Of course, you can make the case, that you can return all relevant data for the view, but it starts to break the single responsibility principle.
Here is an interesting blog post, which might give a better example, why the view should always get the state after the ViewModel: https://medium.com/upday-devs/mvvm-rxjava-learnings-1819423f9592
To the point of the other case, the wikipedia article about MVVM https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93viewmodel states, that the ViewModel can expose public properties.
So in the end, it will most probably be cleaner if you do not return data directly. However, you are the architect and you know your app the best and there might be cases where patterns can be broken. After all they are guidelines. If you know why you break it (and maybe document it), then everything should work out.
I wonder why all Table Views (also in Android) have to have special object that provide them data ?
https://developer.apple.com/library/ios/documentation/uikit/reference/UITableView_Class/Reference/Reference.html#//apple_ref/occ/instp/UITableView/dataSource
Why Table Views can't be populated from controllers (or Activity class in the case of Android) ?
For example UILabel in iOS can be populated just by setting "text" property
https://developer.apple.com/library/ios/documentation/uikit/reference/UILabel_Class/Reference/UILabel.html#//apple_ref/occ/instp/UILabel/text
Could you explain what is the purpose of such design ?
This is a really great question.
We can break this into two reasons - a general one and a specific one that is a common example of it.
First, though, notice that it's even more than that. A UITableView can have two delegate controller objects, a UITableViewDataSourceDelegate and a UITableViewDelegate. The first provides the data; the second responds to actions taken on the displayed data. Why all these layers of abstraction? Why not just stick it in the UIViewController?
The general reason not to is suggested by the name 'UIViewController'. It's meant to control views. In iOS and I expect in android-land, there is a strong temptation to just 'stick it in the view controller' - leading to the Very Large View Controller antipattern, which you can read about a lot (eg here).
Far better for maintenance and organization for the view controller to lay out views and handle button presses, and some other controller object to handle the well-defined and really quite separate responsibility of providing the data.
It's not uncommon to have some sort of object that handles the data anyway - a shopping cart, or list of real estate properties, etc - that encapsulates additional business logic (providing subtotals, for example) but fundamentally already 'has' the data. In that case, provide a category or a lightweight controller that can 'bridge' between that data and the table view, and pass the model object, instead of an array, between view controllers.
This gets into the specific: in iOS, we have things like NSFetchedResultsController. This is a fantastic class that does a tremendous amount of data sorting, pagination, addition, deletion, slicing, dicing, folding, spindling, and mutilating for you - and it also speaks UITableView's language natively. Pass one of those around and you keep your view controllers clean and tidy and separate from your data.
TableViews do need a special or separate object but they do require an object implement the correct protocol so that it can find the data. In Apple's default implementation, it Uses a UTableViewCotnroller that is a new object responds to these methods as well as does some other things such as making the UITableView the root view of the view controller.
If you do not want to use that object for whatever reason you can still manually add a UITableView to your view controller, then sets its delegate to the view controller. Although it is a good to move it out of the view controller if possible to help keep the view controller small and the data reusable.